2017-01-22 Matthias Klose <doko@ubuntu.com>
[platform/upstream/gcc.git] / gcc / genrecog.c
index e152b34..f414d5f 100644 (file)
@@ -1,5 +1,5 @@
 /* Generate code from machine description to recognize rtl as insns.
-   Copyright (C) 1987-2015 Free Software Foundation, Inc.
+   Copyright (C) 1987-2017 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
    5. Write out C++ code for each function.  */
 
 #include "bconfig.h"
+#define INCLUDE_ALGORITHM
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
 #include "errors.h"
 #include "read-md.h"
 #include "gensupport.h"
-#include "hash-table.h"
-#include "inchash.h"
-#include <algorithm>
 
 #undef GENERATOR_FILE
 enum true_rtx_doe {
@@ -172,17 +170,17 @@ static const bool force_unique_params_p = true;
 /* The maximum (approximate) depth of block nesting that an individual
    routine or subroutine should have.  This limit is about keeping the
    output readable rather than reducing compile time.  */
-static const int MAX_DEPTH = 6;
+static const unsigned int MAX_DEPTH = 6;
 
 /* The minimum number of pseudo-statements that a state must have before
    we split it out into a subroutine.  */
-static const int MIN_NUM_STATEMENTS = 5;
+static const unsigned int MIN_NUM_STATEMENTS = 5;
 
 /* The number of pseudo-statements a state can have before we consider
    splitting out substates into subroutines.  This limit is about avoiding
    compile-time problems with very big functions (and also about keeping
    functions within --param optimization limits, etc.).  */
-static const int MAX_NUM_STATEMENTS = 200;
+static const unsigned int MAX_NUM_STATEMENTS = 200;
 
 /* The minimum number of pseudo-statements that can be used in a pattern
    routine.  */
@@ -252,12 +250,6 @@ enum routine_type {
   SUBPATTERN, RECOG, SPLIT, PEEPHOLE2
 };
 
-/* Next number to use as an insn_code.  */
-static int next_insn_code;
-
-/* The line number of the start of the pattern currently being processed.  */
-static int pattern_lineno;
-
 /* The root position (x0).  */
 static struct position root_pos;
 
@@ -396,7 +388,7 @@ find_operand (rtx pattern, int n, rtx stop)
              return r;
          break;
 
-       case 'i': case 'w': case '0': case 's':
+       case 'i': case 'r': case 'w': case '0': case 's':
          break;
 
        default:
@@ -447,7 +439,7 @@ find_matching_operand (rtx pattern, int n)
              return r;
          break;
 
-       case 'i': case 'w': case '0': case 's':
+       case 'i': case 'r': case 'w': case '0': case 's':
          break;
 
        default:
@@ -471,12 +463,45 @@ constraints_supported_in_insn_p (rtx insn)
           || GET_CODE (insn) == DEFINE_PEEPHOLE2);
 }
 
-/* Check for various errors in patterns.  SET is nonnull for a destination,
-   and is the complete set pattern.  SET_CODE is '=' for normal sets, and
-   '+' within a context that requires in-out constraints.  */
+/* Return the name of the predicate matched by MATCH_RTX.  */
+
+static const char *
+predicate_name (rtx match_rtx)
+{
+  if (GET_CODE (match_rtx) == MATCH_SCRATCH)
+    return "scratch_operand";
+  else
+    return XSTR (match_rtx, 1);
+}
+
+/* Return true if OPERAND is a MATCH_OPERAND using a special predicate
+   function.  */
+
+static bool
+special_predicate_operand_p (rtx operand)
+{
+  if (GET_CODE (operand) == MATCH_OPERAND)
+    {
+      const char *pred_name = predicate_name (operand);
+      if (pred_name[0] != 0)
+       {
+         const struct pred_data *pred;
+
+         pred = lookup_predicate (pred_name);
+         return pred != NULL && pred->special;
+       }
+    }
+
+  return false;
+}
+
+/* Check for various errors in PATTERN, which is part of INFO.
+   SET is nonnull for a destination, and is the complete set pattern.
+   SET_CODE is '=' for normal sets, and '+' within a context that
+   requires in-out constraints.  */
 
 static void
-validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
+validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
 {
   const char *fmt;
   RTX_CODE code;
@@ -490,13 +515,12 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
       {
        const char constraints0 = XSTR (pattern, 1)[0];
 
-       if (!constraints_supported_in_insn_p (insn))
+       if (!constraints_supported_in_insn_p (info->def))
          {
            if (constraints0)
              {
-               error_with_line (pattern_lineno,
-                                "constraints not supported in %s",
-                                rtx_name[GET_CODE (insn)]);
+               error_at (info->loc, "constraints not supported in %s",
+                         GET_RTX_NAME (GET_CODE (info->def)));
              }
            return;
          }
@@ -508,19 +532,17 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
            && constraints0 != '='
            && constraints0 != '+')
          {
-           error_with_line (pattern_lineno,
-                            "operand %d missing output reload",
-                            XINT (pattern, 0));
+           error_at (info->loc, "operand %d missing output reload",
+                     XINT (pattern, 0));
          }
        return;
       }
     case MATCH_DUP:
     case MATCH_OP_DUP:
     case MATCH_PAR_DUP:
-      if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
-       error_with_line (pattern_lineno,
-                        "operand %i duplicated before defined",
-                        XINT (pattern, 0));
+      if (find_operand (info->def, XINT (pattern, 0), pattern) == pattern)
+       error_at (info->loc, "operand %i duplicated before defined",
+                 XINT (pattern, 0));
       break;
     case MATCH_OPERAND:
     case MATCH_OPERATOR:
@@ -529,17 +551,13 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
        const struct pred_data *pred;
        const char *c_test;
 
-       if (GET_CODE (insn) == DEFINE_INSN)
-         c_test = XSTR (insn, 2);
-       else
-         c_test = XSTR (insn, 1);
+       c_test = get_c_test (info->def);
 
        if (pred_name[0] != 0)
          {
            pred = lookup_predicate (pred_name);
            if (!pred)
-             error_with_line (pattern_lineno, "unknown predicate '%s'",
-                              pred_name);
+             error_at (info->loc, "unknown predicate '%s'", pred_name);
          }
        else
          pred = 0;
@@ -549,13 +567,12 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
            const char *constraints = XSTR (pattern, 2);
            const char constraints0 = constraints[0];
 
-           if (!constraints_supported_in_insn_p (insn))
+           if (!constraints_supported_in_insn_p (info->def))
              {
                if (constraints0)
                  {
-                   error_with_line (pattern_lineno,
-                                    "constraints not supported in %s",
-                                    rtx_name[GET_CODE (insn)]);
+                   error_at (info->loc, "constraints not supported in %s",
+                             GET_RTX_NAME (GET_CODE (info->def)));
                  }
              }
 
@@ -569,17 +586,16 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
                    /* If we've only got an output reload for this operand,
                       we'd better have a matching input operand.  */
                    else if (constraints0 == '='
-                            && find_matching_operand (insn, XINT (pattern, 0)))
+                            && find_matching_operand (info->def,
+                                                      XINT (pattern, 0)))
                      ;
                    else
-                     error_with_line (pattern_lineno,
-                                      "operand %d missing in-out reload",
-                                      XINT (pattern, 0));
+                     error_at (info->loc, "operand %d missing in-out reload",
+                               XINT (pattern, 0));
                  }
                else if (constraints0 != '=' && constraints0 != '+')
-                 error_with_line (pattern_lineno,
-                                  "operand %d missing output reload",
-                                  XINT (pattern, 0));
+                 error_at (info->loc, "operand %d missing output reload",
+                           XINT (pattern, 0));
              }
 
            /* For matching constraint in MATCH_OPERAND, the digit must be a
@@ -599,10 +615,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
 
                    sscanf (constraints, "%d", &val);
                    if (val >= XINT (pattern, 0))
-                     error_with_line (pattern_lineno,
-                                      "constraint digit %d is not smaller than"
-                                      " operand %d",
-                                      val, XINT (pattern, 0));
+                     error_at (info->loc, "constraint digit %d is not"
+                               " smaller than operand %d",
+                               val, XINT (pattern, 0));
                  }
 
                while (constraints[0] && constraints[0] != ',')
@@ -614,9 +629,8 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
           while not likely to occur at runtime, results in less efficient
           code from insn-recog.c.  */
        if (set && pred && pred->allows_non_lvalue)
-         error_with_line (pattern_lineno,
-                          "destination operand %d allows non-lvalue",
-                          XINT (pattern, 0));
+         error_at (info->loc, "destination operand %d allows non-lvalue",
+                   XINT (pattern, 0));
 
        /* A modeless MATCH_OPERAND can be handy when we can check for
           multiple modes in the c_test.  In most other cases, it is a
@@ -628,7 +642,7 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
 
        if (GET_MODE (pattern) == VOIDmode
            && code == MATCH_OPERAND
-           && GET_CODE (insn) == DEFINE_INSN
+           && GET_CODE (info->def) == DEFINE_INSN
            && pred
            && !pred->special
            && pred->allows_non_const
@@ -636,9 +650,8 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
            && ! (set
                  && GET_CODE (set) == SET
                  && GET_CODE (SET_SRC (set)) == CALL))
-         message_with_line (pattern_lineno,
-                            "warning: operand %d missing mode?",
-                            XINT (pattern, 0));
+         message_at (info->loc, "warning: operand %d missing mode?",
+                     XINT (pattern, 0));
        return;
       }
 
@@ -660,28 +673,26 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
        if (GET_CODE (dest) == MATCH_DUP
            || GET_CODE (dest) == MATCH_OP_DUP
            || GET_CODE (dest) == MATCH_PAR_DUP)
-         dest = find_operand (insn, XINT (dest, 0), NULL);
+         dest = find_operand (info->def, XINT (dest, 0), NULL);
 
        if (GET_CODE (src) == MATCH_DUP
            || GET_CODE (src) == MATCH_OP_DUP
            || GET_CODE (src) == MATCH_PAR_DUP)
-         src = find_operand (insn, XINT (src, 0), NULL);
+         src = find_operand (info->def, XINT (src, 0), NULL);
 
        dmode = GET_MODE (dest);
        smode = GET_MODE (src);
 
-       /* The mode of an ADDRESS_OPERAND is the mode of the memory
-          reference, not the mode of the address.  */
-       if (GET_CODE (src) == MATCH_OPERAND
-           && ! strcmp (XSTR (src, 1), "address_operand"))
+       /* Mode checking is not performed for special predicates.  */
+       if (special_predicate_operand_p (src)
+           || special_predicate_operand_p (dest))
          ;
 
         /* The operands of a SET must have the same mode unless one
           is VOIDmode.  */
         else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
-         error_with_line (pattern_lineno,
-                          "mode mismatch in set: %smode vs %smode",
-                          GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
+         error_at (info->loc, "mode mismatch in set: %smode vs %smode",
+                   GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
 
        /* If only one of the operands is VOIDmode, and PC or CC0 is
           not involved, it's probably a mistake.  */
@@ -696,36 +707,34 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
          {
            const char *which;
            which = (dmode == VOIDmode ? "destination" : "source");
-           message_with_line (pattern_lineno,
-                              "warning: %s missing a mode?", which);
+           message_at (info->loc, "warning: %s missing a mode?", which);
          }
 
        if (dest != SET_DEST (pattern))
-         validate_pattern (dest, insn, pattern, '=');
-       validate_pattern (SET_DEST (pattern), insn, pattern, '=');
-        validate_pattern (SET_SRC (pattern), insn, NULL_RTX, 0);
+         validate_pattern (dest, info, pattern, '=');
+       validate_pattern (SET_DEST (pattern), info, pattern, '=');
+        validate_pattern (SET_SRC (pattern), info, NULL_RTX, 0);
         return;
       }
 
     case CLOBBER:
-      validate_pattern (SET_DEST (pattern), insn, pattern, '=');
+      validate_pattern (SET_DEST (pattern), info, pattern, '=');
       return;
 
     case ZERO_EXTRACT:
-      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
-      validate_pattern (XEXP (pattern, 1), insn, NULL_RTX, 0);
-      validate_pattern (XEXP (pattern, 2), insn, NULL_RTX, 0);
+      validate_pattern (XEXP (pattern, 0), info, set, set ? '+' : 0);
+      validate_pattern (XEXP (pattern, 1), info, NULL_RTX, 0);
+      validate_pattern (XEXP (pattern, 2), info, NULL_RTX, 0);
       return;
 
     case STRICT_LOW_PART:
-      validate_pattern (XEXP (pattern, 0), insn, set, set ? '+' : 0);
+      validate_pattern (XEXP (pattern, 0), info, set, set ? '+' : 0);
       return;
 
     case LABEL_REF:
-      if (GET_MODE (LABEL_REF_LABEL (pattern)) != VOIDmode)
-       error_with_line (pattern_lineno,
-                        "operand to label_ref %smode not VOIDmode",
-                        GET_MODE_NAME (GET_MODE (LABEL_REF_LABEL (pattern))));
+      if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
+       error_at (info->loc, "operand to label_ref %smode not VOIDmode",
+                 GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
       break;
 
     default:
@@ -739,15 +748,15 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
       switch (fmt[i])
        {
        case 'e': case 'u':
-         validate_pattern (XEXP (pattern, i), insn, NULL_RTX, 0);
+         validate_pattern (XEXP (pattern, i), info, NULL_RTX, 0);
          break;
 
        case 'E':
          for (j = 0; j < XVECLEN (pattern, i); j++)
-           validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX, 0);
+           validate_pattern (XVECEXP (pattern, i, j), info, NULL_RTX, 0);
          break;
 
-       case 'i': case 'w': case '0': case 's':
+       case 'i': case 'r': case 'w': case '0': case 's':
          break;
 
        default:
@@ -967,6 +976,9 @@ struct parameter
     /* An int parameter.  */
     INT,
 
+    /* An unsigned int parameter.  */
+    UINT,
+
     /* A HOST_WIDE_INT parameter.  */
     WIDE_INT
   };
@@ -1047,9 +1059,9 @@ struct pattern_use
 };
 
 /* Represents a test performed by a decision.  */
-struct test
+struct rtx_test
 {
-  test ();
+  rtx_test ();
 
   /* The types of test that can be performed.  Most of them take as input
      an rtx X.  Some also take as input a transition label LABEL; the others
@@ -1063,6 +1075,9 @@ struct test
     /* Check GET_MODE (X) == LABEL.  */
     MODE,
 
+    /* Check REGNO (X) == LABEL.  */
+    REGNO_FIELD,
+
     /* Check XINT (X, u.opno) == LABEL.  */
     INT_FIELD,
 
@@ -1140,136 +1155,144 @@ struct test
     acceptance_type acceptance;
   } u;
 
-  static test code (position *);
-  static test mode (position *);
-  static test int_field (position *, int);
-  static test wide_int_field (position *, int);
-  static test veclen (position *);
-  static test peep2_count (int);
-  static test veclen_ge (position *, int);
-  static test predicate (position *, const pred_data *, machine_mode);
-  static test duplicate (position *, int);
-  static test pattern (position *, pattern_use *);
-  static test have_num_clobbers ();
-  static test c_test (const char *);
-  static test set_op (position *, int);
-  static test accept (const acceptance_type &);
+  static rtx_test code (position *);
+  static rtx_test mode (position *);
+  static rtx_test regno_field (position *);
+  static rtx_test int_field (position *, int);
+  static rtx_test wide_int_field (position *, int);
+  static rtx_test veclen (position *);
+  static rtx_test peep2_count (int);
+  static rtx_test veclen_ge (position *, int);
+  static rtx_test predicate (position *, const pred_data *, machine_mode);
+  static rtx_test duplicate (position *, int);
+  static rtx_test pattern (position *, pattern_use *);
+  static rtx_test have_num_clobbers ();
+  static rtx_test c_test (const char *);
+  static rtx_test set_op (position *, int);
+  static rtx_test accept (const acceptance_type &);
 
   bool terminal_p () const;
   bool single_outcome_p () const;
 
 private:
-  test (position *, kind_enum);
+  rtx_test (position *, kind_enum);
 };
 
-test::test () {}
+rtx_test::rtx_test () {}
 
-test::test (position *pos_in, kind_enum kind_in)
+rtx_test::rtx_test (position *pos_in, kind_enum kind_in)
   : pos (pos_in), pos_operand (-1), kind (kind_in) {}
 
-test
-test::code (position *pos)
+rtx_test
+rtx_test::code (position *pos)
+{
+  return rtx_test (pos, rtx_test::CODE);
+}
+
+rtx_test
+rtx_test::mode (position *pos)
 {
-  return test (pos, test::CODE);
+  return rtx_test (pos, rtx_test::MODE);
 }
 
-test
-test::mode (position *pos)
+rtx_test
+rtx_test::regno_field (position *pos)
 {
-  return test (pos, test::MODE);
+  rtx_test res (pos, rtx_test::REGNO_FIELD);
+  return res;
 }
 
-test
-test::int_field (position *pos, int opno)
+rtx_test
+rtx_test::int_field (position *pos, int opno)
 {
-  test res (pos, test::INT_FIELD);
+  rtx_test res (pos, rtx_test::INT_FIELD);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::wide_int_field (position *pos, int opno)
+rtx_test
+rtx_test::wide_int_field (position *pos, int opno)
 {
-  test res (pos, test::WIDE_INT_FIELD);
+  rtx_test res (pos, rtx_test::WIDE_INT_FIELD);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::veclen (position *pos)
+rtx_test
+rtx_test::veclen (position *pos)
 {
-  return test (pos, test::VECLEN);
+  return rtx_test (pos, rtx_test::VECLEN);
 }
 
-test
-test::peep2_count (int min_len)
+rtx_test
+rtx_test::peep2_count (int min_len)
 {
-  test res (0, test::PEEP2_COUNT);
+  rtx_test res (0, rtx_test::PEEP2_COUNT);
   res.u.min_len = min_len;
   return res;
 }
 
-test
-test::veclen_ge (position *pos, int min_len)
+rtx_test
+rtx_test::veclen_ge (position *pos, int min_len)
 {
-  test res (pos, test::VECLEN_GE);
+  rtx_test res (pos, rtx_test::VECLEN_GE);
   res.u.min_len = min_len;
   return res;
 }
 
-test
-test::predicate (position *pos, const struct pred_data *data,
-                machine_mode mode)
+rtx_test
+rtx_test::predicate (position *pos, const struct pred_data *data,
+                    machine_mode mode)
 {
-  test res (pos, test::PREDICATE);
+  rtx_test res (pos, rtx_test::PREDICATE);
   res.u.predicate.data = data;
   res.u.predicate.mode_is_param = false;
   res.u.predicate.mode = mode;
   return res;
 }
 
-test
-test::duplicate (position *pos, int opno)
+rtx_test
+rtx_test::duplicate (position *pos, int opno)
 {
-  test res (pos, test::DUPLICATE);
+  rtx_test res (pos, rtx_test::DUPLICATE);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::pattern (position *pos, pattern_use *pattern)
+rtx_test
+rtx_test::pattern (position *pos, pattern_use *pattern)
 {
-  test res (pos, test::PATTERN);
+  rtx_test res (pos, rtx_test::PATTERN);
   res.u.pattern = pattern;
   return res;
 }
 
-test
-test::have_num_clobbers ()
+rtx_test
+rtx_test::have_num_clobbers ()
 {
-  return test (0, test::HAVE_NUM_CLOBBERS);
+  return rtx_test (0, rtx_test::HAVE_NUM_CLOBBERS);
 }
 
-test
-test::c_test (const char *string)
+rtx_test
+rtx_test::c_test (const char *string)
 {
-  test res (0, test::C_TEST);
+  rtx_test res (0, rtx_test::C_TEST);
   res.u.string = string;
   return res;
 }
 
-test
-test::set_op (position *pos, int opno)
+rtx_test
+rtx_test::set_op (position *pos, int opno)
 {
-  test res (pos, test::SET_OP);
+  rtx_test res (pos, rtx_test::SET_OP);
   res.u.opno = opno;
   return res;
 }
 
-test
-test::accept (const acceptance_type &acceptance)
+rtx_test
+rtx_test::accept (const acceptance_type &acceptance)
 {
-  test res (0, test::ACCEPT);
+  rtx_test res (0, rtx_test::ACCEPT);
   res.u.acceptance = acceptance;
   return res;
 }
@@ -1277,66 +1300,67 @@ test::accept (const acceptance_type &acceptance)
 /* Return true if the test represents an unconditionally successful match.  */
 
 bool
-test::terminal_p () const
+rtx_test::terminal_p () const
 {
-  return kind == test::ACCEPT && u.acceptance.type != PEEPHOLE2;
+  return kind == rtx_test::ACCEPT && u.acceptance.type != PEEPHOLE2;
 }
 
 /* Return true if the test is a boolean that is always true.  */
 
 bool
-test::single_outcome_p () const
+rtx_test::single_outcome_p () const
 {
-  return terminal_p () || kind == test::SET_OP;
+  return terminal_p () || kind == rtx_test::SET_OP;
 }
 
 bool
-operator == (const test &a, const test &b)
+operator == (const rtx_test &a, const rtx_test &b)
 {
   if (a.pos != b.pos || a.kind != b.kind)
     return false;
   switch (a.kind)
     {
-    case test::CODE:
-    case test::MODE:
-    case test::VECLEN:
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::REGNO_FIELD:
+    case rtx_test::VECLEN:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       return true;
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
       return a.u.min_len == b.u.min_len;
 
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::DUPLICATE:
-    case test::SET_OP:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::DUPLICATE:
+    case rtx_test::SET_OP:
       return a.u.opno == b.u.opno;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       return (a.u.integer.is_param == b.u.integer.is_param
              && a.u.integer.value == b.u.integer.value);
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       return (a.u.predicate.data == b.u.predicate.data
              && a.u.predicate.mode_is_param == b.u.predicate.mode_is_param
              && a.u.predicate.mode == b.u.predicate.mode);
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       return (a.u.pattern->routine == b.u.pattern->routine
              && a.u.pattern->params == b.u.pattern->params);
 
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       return strcmp (a.u.string, b.u.string) == 0;
 
-    case test::ACCEPT:
+    case rtx_test::ACCEPT:
       return a.u.acceptance == b.u.acceptance;
     }
   gcc_unreachable ();
 }
 
 bool
-operator != (const test &a, const test &b)
+operator != (const rtx_test &a, const rtx_test &b)
 {
   return !operator == (a, b);
 }
@@ -1420,8 +1444,8 @@ struct transition
   transition *prev, *next;
 
   /* The transition should be taken when T has one of these values.
-     E.g. for test::CODE this is a set of codes, while for booleans like
-     test::PREDICATE it is always a singleton "true".  The labels are
+     E.g. for rtx_test::CODE this is a set of codes, while for booleans like
+     rtx_test::PREDICATE it is always a singleton "true".  The labels are
      sorted in ascending order.  */
   int_set labels;
 
@@ -1439,7 +1463,7 @@ struct transition
   bool optional;
 
   /* True if LABELS contains parameter numbers rather than constants.
-     E.g. if this is true for a test::CODE, the label is the number
+     E.g. if this is true for a rtx_test::CODE, the label is the number
      of an rtx_code parameter rather than an rtx_code itself.
      LABELS is always a singleton when this variable is true.  */
   bool is_param;
@@ -1452,7 +1476,7 @@ struct transition
    more decisions to try, fails the match.  */
 struct decision : list_head <transition>
 {
-  decision (const test &);
+  decision (const rtx_test &);
 
   void set_parent (list_head <decision> *s);
   bool if_statement_p (uint64_t * = 0) const;
@@ -1464,7 +1488,7 @@ struct decision : list_head <transition>
   decision *prev, *next;
 
   /* The test to perform.  */
-  struct test test;
+  rtx_test test;
 };
 
 /* Represents one machine state.  For each state the machine tries a list
@@ -1488,7 +1512,7 @@ transition::set_parent (list_head <transition> *from_in)
   from = static_cast <decision *> (from_in);
 }
 
-decision::decision (const struct test &test_in)
+decision::decision (const rtx_test &test_in)
   : prev (0), next (0), test (test_in) {}
 
 /* Set the state to which this decision belongs.  */
@@ -1518,7 +1542,7 @@ decision::if_statement_p (uint64_t *label) const
    TRANS.  */
 
 static void
-add_decision (state *from, const test &test, transition *trans)
+add_decision (state *from, const rtx_test &test, transition *trans)
 {
   decision *d = new decision (test);
   from->push_back (d);
@@ -1530,7 +1554,7 @@ add_decision (state *from, const test &test, transition *trans)
    should be optional.  Return the new state.  */
 
 static state *
-add_decision (state *from, const test &test, int_set labels, bool optional)
+add_decision (state *from, const rtx_test &test, int_set labels, bool optional)
 {
   state *to = new state;
   add_decision (from, test, new transition (labels, to, optional));
@@ -1542,7 +1566,7 @@ add_decision (state *from, const test &test, int_set labels, bool optional)
    optional.  */
 
 static decision *
-insert_decision_before (state::range r, const test &test,
+insert_decision_before (state::range r, const rtx_test &test,
                        const int_set &labels, bool optional)
 {
   decision *newd = new decision (test);
@@ -1593,17 +1617,18 @@ simplify_tests (state *s)
       uint64_t label;
       /* Convert checks for GET_CODE (x) == CONST_INT and XWINT (x, 0) == N
         into checks for const_int_rtx[N'], if N is suitably small.  */
-      if (d->test.kind == test::CODE
+      if (d->test.kind == rtx_test::CODE
          && d->if_statement_p (&label)
          && label == CONST_INT)
        if (decision *second = d->first->to->singleton ())
-         if (second->test.kind == test::WIDE_INT_FIELD
+         if (d->test.pos == second->test.pos
+             && second->test.kind == rtx_test::WIDE_INT_FIELD
              && second->test.u.opno == 0
              && second->if_statement_p (&label)
              && IN_RANGE (int64_t (label),
                           -MAX_SAVED_CONST_INT, MAX_SAVED_CONST_INT))
            {
-             d->test.kind = test::SAVED_CONST_INT;
+             d->test.kind = rtx_test::SAVED_CONST_INT;
              d->test.u.integer.is_param = false;
              d->test.u.integer.value = label;
              d->replace (d->first, second->release ());
@@ -1618,7 +1643,7 @@ simplify_tests (state *s)
         paths that reach that code test require the same predicate
         to be true.  cse_tests will then put the predicate test in
         series with the code test.  */
-      if (d->test.kind == test::CODE)
+      if (d->test.kind == rtx_test::CODE)
        if (transition *trans = d->singleton ())
          {
            state *s = trans->to;
@@ -1629,7 +1654,7 @@ simplify_tests (state *s)
                transition *trans2 = d2->singleton ();
                if (!trans2)
                  break;
-               if (d2->test.kind == test::PREDICATE)
+               if (d2->test.kind == rtx_test::PREDICATE)
                  {
                    d->test = d2->test;
                    trans->labels = int_set (true);
@@ -1653,7 +1678,7 @@ simplify_tests (state *s)
 static bool
 common_test_p (decision *d, transition *common, vec <transition *> *where)
 {
-  if (d->test.kind == test::ACCEPT)
+  if (d->test.kind == rtx_test::ACCEPT)
     /* We found a successful return that didn't require COMMON.  */
     return false;
   if (d->test == common->from->test)
@@ -1701,20 +1726,20 @@ struct known_conditions
    as positive proof.  */
 
 static bool
-safe_to_hoist_p (decision *d, const test &test, known_conditions *kc)
+safe_to_hoist_p (decision *d, const rtx_test &test, known_conditions *kc)
 {
   switch (test.kind)
     {
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       /* In general, C tests require everything else to have been
         verified and all operands to have been set up.  */
       return false;
 
-    case test::ACCEPT:
+    case rtx_test::ACCEPT:
       /* Don't accept something before all conditions have been tested.  */
       return false;
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       /* Don't move a predicate over a test for VECLEN_GE, since the
         predicate used in a match_parallel can legitimately expect the
         length to be checked first.  */
@@ -1722,21 +1747,21 @@ safe_to_hoist_p (decision *d, const test &test, known_conditions *kc)
           subd->test != test;
           subd = subd->first->to->first)
        if (subd->test.pos == test.pos
-           && subd->test.kind == test::VECLEN_GE)
+           && subd->test.kind == rtx_test::VECLEN_GE)
          return false;
       goto any_rtx;
 
-    case test::DUPLICATE:
+    case rtx_test::DUPLICATE:
       /* Don't test for a match_dup until the associated operand has
         been set.  */
       if (!kc->set_operands[test.u.opno])
        return false;
       goto any_rtx;
 
-    case test::CODE:
-    case test::MODE:
-    case test::SAVED_CONST_INT:
-    case test::SET_OP:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::SET_OP:
     any_rtx:
       /* Check whether it is safe to access the rtx under test.  */
       switch (test.pos->type)
@@ -1752,20 +1777,21 @@ safe_to_hoist_p (decision *d, const test &test, known_conditions *kc)
        }
       gcc_unreachable ();
 
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::VECLEN:
-    case test::VECLEN_GE:
+    case rtx_test::REGNO_FIELD:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::VECLEN:
+    case rtx_test::VECLEN_GE:
       /* These tests access a specific part of an rtx, so are only safe
         once we know what the rtx is.  */
       return kc->position_tests[test.pos->id] & TESTED_CODE;
 
-    case test::PEEP2_COUNT:
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       /* These tests can be performed anywhere.  */
       return true;
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       gcc_unreachable ();
     }
   gcc_unreachable ();
@@ -1886,8 +1912,8 @@ cse_tests (position *pos, state *s, known_conditions *kc)
       /* Make sure that safe_to_hoist_p isn't being overly conservative.
         It should realize that D's test is safe in the current
         environment.  */
-      gcc_assert (d->test.kind == test::C_TEST
-                 || d->test.kind == test::ACCEPT
+      gcc_assert (d->test.kind == rtx_test::C_TEST
+                 || d->test.kind == rtx_test::ACCEPT
                  || safe_to_hoist_p (d, d->test, kc));
 
       /* D won't be changed any further by the current optimization.
@@ -1895,24 +1921,24 @@ cse_tests (position *pos, state *s, known_conditions *kc)
       int prev = 0;
       switch (d->test.kind)
        {
-       case test::CODE:
+       case rtx_test::CODE:
          prev = kc->position_tests[d->test.pos->id];
          kc->position_tests[d->test.pos->id] |= TESTED_CODE;
          break;
 
-       case test::VECLEN:
-       case test::VECLEN_GE:
+       case rtx_test::VECLEN:
+       case rtx_test::VECLEN_GE:
          prev = kc->position_tests[d->test.pos->id];
          kc->position_tests[d->test.pos->id] |= TESTED_VECLEN;
          break;
 
-       case test::SET_OP:
+       case rtx_test::SET_OP:
          prev = kc->set_operands[d->test.u.opno];
          gcc_assert (!prev);
          kc->set_operands[d->test.u.opno] = true;
          break;
 
-       case test::PEEP2_COUNT:
+       case rtx_test::PEEP2_COUNT:
          prev = kc->peep2_count;
          kc->peep2_count = MAX (prev, d->test.u.min_len);
          break;
@@ -1924,17 +1950,17 @@ cse_tests (position *pos, state *s, known_conditions *kc)
        cse_tests (d->test.pos ? d->test.pos : pos, trans->to, kc);
       switch (d->test.kind)
        {
-       case test::CODE:
-       case test::VECLEN:
-       case test::VECLEN_GE:
+       case rtx_test::CODE:
+       case rtx_test::VECLEN:
+       case rtx_test::VECLEN_GE:
          kc->position_tests[d->test.pos->id] = prev;
          break;
 
-       case test::SET_OP:
+       case rtx_test::SET_OP:
          kc->set_operands[d->test.u.opno] = prev;
          break;
 
-       case test::PEEP2_COUNT:
+       case rtx_test::PEEP2_COUNT:
          kc->peep2_count = prev;
          break;
 
@@ -1948,33 +1974,36 @@ cse_tests (position *pos, state *s, known_conditions *kc)
    or parameter::UNSET if none.  */
 
 parameter::type_enum
-transition_parameter_type (test::kind_enum kind)
+transition_parameter_type (rtx_test::kind_enum kind)
 {
   switch (kind)
     {
-    case test::CODE:
+    case rtx_test::CODE:
       return parameter::CODE;
 
-    case test::MODE:
+    case rtx_test::MODE:
       return parameter::MODE;
 
-    case test::INT_FIELD:
-    case test::VECLEN:
-    case test::PATTERN:
+    case rtx_test::REGNO_FIELD:
+      return parameter::UINT;
+
+    case rtx_test::INT_FIELD:
+    case rtx_test::VECLEN:
+    case rtx_test::PATTERN:
       return parameter::INT;
 
-    case test::WIDE_INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
       return parameter::WIDE_INT;
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
-    case test::SAVED_CONST_INT:
-    case test::PREDICATE:
-    case test::DUPLICATE:
-    case test::HAVE_NUM_CLOBBERS:
-    case test::C_TEST:
-    case test::SET_OP:
-    case test::ACCEPT:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::PREDICATE:
+    case rtx_test::DUPLICATE:
+    case rtx_test::HAVE_NUM_CLOBBERS:
+    case rtx_test::C_TEST:
+    case rtx_test::SET_OP:
+    case rtx_test::ACCEPT:
       return parameter::UNSET;
     }
   gcc_unreachable ();
@@ -1992,11 +2021,11 @@ find_operand_positions (state *s, vec <int> &operand_pos)
       int this_operand = (d->test.pos ? operand_pos[d->test.pos->id] : -1);
       if (this_operand >= 0)
        d->test.pos_operand = this_operand;
-      if (d->test.kind == test::SET_OP)
+      if (d->test.kind == rtx_test::SET_OP)
        operand_pos[d->test.pos->id] = d->test.u.opno;
       for (transition *trans = d->first; trans; trans = trans->next)
        find_operand_positions (trans->to, operand_pos);
-      if (d->test.kind == test::SET_OP)
+      if (d->test.kind == rtx_test::SET_OP)
        operand_pos[d->test.pos->id] = this_operand;
     }
 }
@@ -2064,7 +2093,7 @@ get_stats (state *s)
          for_d.num_decisions += 1;
          for_d.longest_path += 1;
        }
-      if (d->test.kind == test::ACCEPT)
+      if (d->test.kind == rtx_test::ACCEPT)
        {
          for_d.longest_path_code = d->test.u.acceptance.u.full.code;
          for_d.longest_backtrack_code = d->test.u.acceptance.u.full.code;
@@ -2378,21 +2407,21 @@ update_parameters (vec <parameter> &to, const vec <parameter> &from)
    PARAMB alone.  */
 
 static bool
-compatible_tests_p (const test &a, const test &b,
+compatible_tests_p (const rtx_test &a, const rtx_test &b,
                    parameter *parama, parameter *paramb)
 {
   if (a.kind != b.kind)
     return false;
   switch (a.kind)
     {
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       if (a.u.predicate.data != b.u.predicate.data)
        return false;
       *parama = parameter (parameter::MODE, false, a.u.predicate.mode);
       *paramb = parameter (parameter::MODE, false, b.u.predicate.mode);
       return true;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       *parama = parameter (parameter::INT, false, a.u.integer.value);
       *paramb = parameter (parameter::INT, false, b.u.integer.value);
       return true;
@@ -2501,10 +2530,8 @@ merge_relative_positions (position **roota, position *a,
 
 /* A hasher of states that treats two states as "equal" if they might be
    merged (but trying to be more discriminating than "return true").  */
-struct test_pattern_hasher : typed_noop_remove <merge_state_info>
+struct test_pattern_hasher : nofree_ptr_hash <merge_state_info>
 {
-  typedef merge_state_info *value_type;
-  typedef merge_state_info *compare_type;
   static inline hashval_t hash (const value_type &);
   static inline bool equal (const value_type &, const compare_type &);
 };
@@ -2666,7 +2693,7 @@ merge_patterns (merge_state_info *sinfo1, merge_state_info *sinfo2)
             parameterizing the first N const_ints of the vector
             and then (once we reach the maximum number of parameters)
             we go on to match the other elements exactly.  */
-         if (d1->test.kind == test::WIDE_INT_FIELD)
+         if (d1->test.kind == rtx_test::WIDE_INT_FIELD)
            return false;
 
          /* See whether the label has a generalizable type.  */
@@ -2802,7 +2829,7 @@ init_pattern_use (create_pattern_info *cpi, merge_state_info *sinfo,
   pattern_use *use = new pattern_use;
   use->routine = pat->routine;
   use->params.splice (params);
-  decision *d = new decision (test::pattern (res->root, use));
+  decision *d = new decision (rtx_test::pattern (res->root, use));
 
   /* If the original decision could use an element of operands[] instead
      of an rtx variable, try to transfer it to the new decision.  */
@@ -2822,7 +2849,7 @@ add_pattern_acceptance (create_pattern_info *cpi, state *s)
   acceptance.type = SUBPATTERN;
   acceptance.partial_p = false;
   acceptance.u.full.code = cpi->next_result;
-  add_decision (s, test::accept (acceptance), true, false);
+  add_decision (s, rtx_test::accept (acceptance), true, false);
   cpi->next_result += 1;
 }
 
@@ -2859,12 +2886,12 @@ populate_pattern_routine (create_pattern_info *cpi, merge_state_info *sinfo,
       const parameter &param = params[pat->param_test];
       switch (newd->test.kind)
        {
-       case test::PREDICATE:
+       case rtx_test::PREDICATE:
          newd->test.u.predicate.mode_is_param = param.is_param;
          newd->test.u.predicate.mode = param.value;
          break;
 
-       case test::SAVED_CONST_INT:
+       case rtx_test::SAVED_CONST_INT:
          newd->test.u.integer.is_param = param.is_param;
          newd->test.u.integer.value = param.value;
          break;
@@ -2874,9 +2901,9 @@ populate_pattern_routine (create_pattern_info *cpi, merge_state_info *sinfo,
          break;
        }
     }
-  if (d->test.kind == test::C_TEST)
+  if (d->test.kind == rtx_test::C_TEST)
     routine->insn_p = true;
-  else if (d->test.kind == test::HAVE_NUM_CLOBBERS)
+  else if (d->test.kind == rtx_test::HAVE_NUM_CLOBBERS)
     routine->pnum_clobbers_p = true;
   news->push_back (newd);
 
@@ -3037,11 +3064,11 @@ split_out_patterns (vec <merge_state_info> &states)
         and so couldn't be shared between states).  */
       if (decision *d = sinfo->s->singleton ())
        /* ACCEPT states are unique, so don't even try to merge them.  */
-       if (d->test.kind != test::ACCEPT
+       if (d->test.kind != rtx_test::ACCEPT
            && (pattern_have_num_clobbers_p
-               || d->test.kind != test::HAVE_NUM_CLOBBERS)
+               || d->test.kind != rtx_test::HAVE_NUM_CLOBBERS)
            && (pattern_c_test_p
-               || d->test.kind != test::C_TEST))
+               || d->test.kind != rtx_test::C_TEST))
          {
            merge_state_info **slot = hashtab.find_slot (sinfo, INSERT);
            sinfo->prev_same_test = *slot;
@@ -3289,7 +3316,7 @@ create_subroutine (routine_type type, state *s, vec <state *> &procs)
   acceptance.partial_p = true;
   acceptance.u.subroutine_id = procs.length ();
   state *news = new state;
-  add_decision (news, test::accept (acceptance), true, false);
+  add_decision (news, rtx_test::accept (acceptance), true, false);
   return news;
 }
 
@@ -3326,8 +3353,8 @@ find_subroutines (routine_type type, state *s, vec <state *> &procs)
                if (!newd->test.single_outcome_p ())
                  size.num_statements += 1;
                trans = newd->singleton ();
-               if (newd->test.kind == test::SET_OP
-                   || newd->test.kind == test::ACCEPT)
+               if (newd->test.kind == rtx_test::SET_OP
+                   || newd->test.kind == rtx_test::ACCEPT)
                  break;
              }
          /* The target of TRANS is a subroutine candidate.  First recurse
@@ -3386,7 +3413,8 @@ safe_predicate_mode (const struct pred_data *pred, machine_mode mode)
   if (GET_MODE_CLASS (mode) == MODE_INT
       && (pred->codes[CONST_INT]
          || pred->codes[CONST_DOUBLE]
-         || pred->codes[CONST_WIDE_INT]))
+         || pred->codes[CONST_WIDE_INT]
+         || pred->codes[LABEL_REF]))
     return false;
 
   return !pred->special && mode != VOIDmode;
@@ -3791,23 +3819,12 @@ operator < (const pattern_pos &e1, const pattern_pos &e2)
   return diff < 0;
 }
 
-/* Return the name of the predicate matched by MATCH_RTX.  */
-
-static const char *
-predicate_name (rtx match_rtx)
-{
-  if (GET_CODE (match_rtx) == MATCH_SCRATCH)
-    return "scratch_operand";
-  else
-    return XSTR (match_rtx, 1);
-}
-
 /* Add new decisions to S that check whether the rtx at position POS
    matches PATTERN.  Return the state that is reached in that case.
    TOP_PATTERN is the overall pattern, as passed to match_pattern_1.  */
 
 static state *
-match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
+match_pattern_2 (state *s, md_rtx_info *info, position *pos, rtx pattern)
 {
   auto_vec <pattern_pos, 32> worklist;
   auto_vec <pattern_pos, 32> pred_and_mode_tests;
@@ -3832,7 +3849,7 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
          dup_tests.safe_push (pattern_pos (pattern, pos));
 
          /* Use the same code check as the original operand.  */
-         pattern = find_operand (top_pattern, XINT (pattern, 0), NULL_RTX);
+         pattern = find_operand (info->def, XINT (pattern, 0), NULL_RTX);
          /* Fall through.  */
 
        case MATCH_PARALLEL:
@@ -3849,25 +3866,22 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
                if (code == GET_CODE (pattern))
                  {
                    if (!pred)
-                     error_with_line (pattern_lineno,
-                                      "unknown predicate '%s'"
-                                      " in '%s' expression",
-                                      pred_name, GET_RTX_NAME (code));
+                     error_at (info->loc, "unknown predicate '%s' used in %s",
+                               pred_name, GET_RTX_NAME (code));
                    else if (code == MATCH_PARALLEL
                             && pred->singleton != PARALLEL)
-                     error_with_line (pattern_lineno,
-                                      "predicate '%s' used in match_parallel"
-                                      " does not allow only PARALLEL",
-                                      pred->name);
+                     error_at (info->loc, "predicate '%s' used in"
+                               " match_parallel does not allow only PARALLEL",
+                               pred->name);
                  }
              }
 
            if (code == MATCH_PARALLEL || code == MATCH_PAR_DUP)
              {
                /* Check that we have a parallel with enough elements.  */
-               s = add_decision (s, test::code (pos), PARALLEL, false);
+               s = add_decision (s, rtx_test::code (pos), PARALLEL, false);
                int min_len = XVECLEN (pattern, 2);
-               s = add_decision (s, test::veclen_ge (pos, min_len),
+               s = add_decision (s, rtx_test::veclen_ge (pos, min_len),
                                  true, false);
              }
            else
@@ -3882,7 +3896,7 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
                bool need_codes = (pred
                                   && (code == MATCH_OPERATOR
                                       || code == MATCH_OP_DUP));
-               s = add_decision (s, test::code (pos), codes, !need_codes);
+               s = add_decision (s, rtx_test::code (pos), codes, !need_codes);
              }
 
            /* Postpone the predicate check until we've checked the rest
@@ -3923,7 +3937,7 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
        default:
          {
            /* Check that the rtx has the right code.  */
-           s = add_decision (s, test::code (pos), code, false);
+           s = add_decision (s, rtx_test::code (pos), code, false);
 
            /* Queue a test for the mode if one is specified.  */
            if (GET_MODE (pattern) != VOIDmode)
@@ -3948,7 +3962,8 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
                      /* Make sure the vector has the right number of
                         elements.  */
                      int length = XVECLEN (pattern, i);
-                     s = add_decision (s, test::veclen (pos), length, false);
+                     s = add_decision (s, rtx_test::veclen (pos),
+                                       length, false);
 
                      position **subpos2_ptr = &pos->xvecexp0s;
                      for (int j = 0; j < length; j++)
@@ -3964,13 +3979,20 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
 
                  case 'i':
                    /* Make sure that XINT (X, I) has the right value.  */
-                   s = add_decision (s, test::int_field (pos, i),
+                   s = add_decision (s, rtx_test::int_field (pos, i),
                                      XINT (pattern, i), false);
                    break;
 
+                 case 'r':
+                   /* Make sure that REGNO (X) has the right value.  */
+                   gcc_assert (i == 0);
+                   s = add_decision (s, rtx_test::regno_field (pos),
+                                     REGNO (pattern), false);
+                   break;
+
                  case 'w':
                    /* Make sure that XWINT (X, I) has the right value.  */
-                   s = add_decision (s, test::wide_int_field (pos, i),
+                   s = add_decision (s, rtx_test::wide_int_field (pos, i),
                                      XWINT (pattern, 0), false);
                    break;
 
@@ -4035,8 +4057,8 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
                /* Check the mode first, to distinguish things like SImode
                   and DImode register_operands, as described above.  */
                machine_mode mode = GET_MODE (e->pattern);
-               if (safe_predicate_mode (pred, mode))
-                 s = add_decision (s, test::mode (e->pos), mode, true);
+               if (pred && safe_predicate_mode (pred, mode))
+                 s = add_decision (s, rtx_test::mode (e->pos), mode, true);
 
                /* Assign to operands[] first, so that the rtx usually doesn't
                   need to be live across the call to the predicate.
@@ -4045,19 +4067,21 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
                   since we fully expect to assign to operands[] at some point,
                   and since the caller usually writes to other parts of
                   recog_data anyway.  */
-               s = add_decision (s, test::set_op (e->pos, opno), true, false);
-               s = add_decision (s, test::predicate (e->pos, pred, mode),
+               s = add_decision (s, rtx_test::set_op (e->pos, opno),
+                                 true, false);
+               s = add_decision (s, rtx_test::predicate (e->pos, pred, mode),
                                  true, false);
              }
            else
              /* Historically we've ignored the mode when there's no
                 predicate.  Just set up operands[] unconditionally.  */
-             s = add_decision (s, test::set_op (e->pos, opno), true, false);
+             s = add_decision (s, rtx_test::set_op (e->pos, opno),
+                               true, false);
            break;
          }
 
        default:
-         s = add_decision (s, test::mode (e->pos),
+         s = add_decision (s, rtx_test::mode (e->pos),
                            GET_MODE (e->pattern), false);
          break;
        }
@@ -4065,7 +4089,7 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
 
   /* Finally add rtx_equal_p checks for duplicated operands.  */
   FOR_EACH_VEC_ELT (dup_tests, i, e)
-    s = add_decision (s, test::duplicate (e->pos, XINT (e->pattern, 0)),
+    s = add_decision (s, rtx_test::duplicate (e->pos, XINT (e->pattern, 0)),
                      true, false);
   return s;
 }
@@ -4074,55 +4098,52 @@ match_pattern_2 (state *s, rtx top_pattern, position *pos, rtx pattern)
 
    (1) the rtx doesn't match anything already matched by S
    (2) the rtx matches TOP_PATTERN and
-   (3) C_TEST is true.
+   (3) the C test required by INFO->def is true
 
-   For peephole2, TOP_PATTERN is the DEFINE_PEEPHOLE2 itself, otherwise
-   it is the rtx pattern to match (PARALLEL, SET, etc.).  */
+   For peephole2, TOP_PATTERN is a SEQUENCE of the instruction patterns
+   to match, otherwise it is a single instruction pattern.  */
 
 static void
-match_pattern_1 (state *s, rtx top_pattern, const char *c_test,
+match_pattern_1 (state *s, md_rtx_info *info, rtx pattern,
                 acceptance_type acceptance)
 {
-  if (GET_CODE (top_pattern) == DEFINE_PEEPHOLE2)
+  if (acceptance.type == PEEPHOLE2)
     {
       /* Match each individual instruction.  */
       position **subpos_ptr = &peep2_insn_pos_list;
       int count = 0;
-      for (int i = 0; i < XVECLEN (top_pattern, 0); ++i)
+      for (int i = 0; i < XVECLEN (pattern, 0); ++i)
        {
-         rtx x = XVECEXP (top_pattern, 0, i);
-         /* Ignore scratch register requirements.  */
-         if (GET_CODE (x) != MATCH_SCRATCH && GET_CODE (x) != MATCH_DUP)
-           {
-             position *subpos = next_position (subpos_ptr, &root_pos,
-                                               POS_PEEP2_INSN, count);
-             if (count > 0)
-               s = add_decision (s, test::peep2_count (count + 1),
-                                 true, false);
-             s = match_pattern_2 (s, top_pattern, subpos, x);
-             subpos_ptr = &subpos->next;
-             count += 1;
-           }
+         rtx x = XVECEXP (pattern, 0, i);
+         position *subpos = next_position (subpos_ptr, &root_pos,
+                                           POS_PEEP2_INSN, count);
+         if (count > 0)
+           s = add_decision (s, rtx_test::peep2_count (count + 1),
+                             true, false);
+         s = match_pattern_2 (s, info, subpos, x);
+         subpos_ptr = &subpos->next;
+         count += 1;
        }
       acceptance.u.full.u.match_len = count - 1;
     }
   else
     {
       /* Make the rtx itself.  */
-      s = match_pattern_2 (s, top_pattern, &root_pos, top_pattern);
+      s = match_pattern_2 (s, info, &root_pos, pattern);
 
       /* If the match is only valid when extra clobbers are added,
         make sure we're able to pass that information to the caller.  */
       if (acceptance.type == RECOG && acceptance.u.full.u.num_clobbers)
-       s = add_decision (s, test::have_num_clobbers (), true, false);
+       s = add_decision (s, rtx_test::have_num_clobbers (), true, false);
     }
 
   /* Make sure that the C test is true.  */
+  const char *c_test = get_c_test (info->def);
   if (maybe_eval_c_test (c_test) != 1)
-    s = add_decision (s, test::c_test (c_test), true, false);
+    s = add_decision (s, rtx_test::c_test (c_test), true, false);
 
   /* Accept the pattern.  */
-  add_decision (s, test::accept (acceptance), true, false);
+  add_decision (s, rtx_test::accept (acceptance), true, false);
 }
 
 /* Like match_pattern_1, but (if merge_states_p) try to merge the
@@ -4130,7 +4151,7 @@ match_pattern_1 (state *s, rtx top_pattern, const char *c_test,
    backtracking.  */
 
 static void
-match_pattern (state *s, rtx top_pattern, const char *c_test,
+match_pattern (state *s, md_rtx_info *info, rtx pattern,
               acceptance_type acceptance)
 {
   if (merge_states_p)
@@ -4138,11 +4159,11 @@ match_pattern (state *s, rtx top_pattern, const char *c_test,
       state root;
       /* Add the decisions to a fresh state and then merge the full tree
         into the existing one.  */
-      match_pattern_1 (&root, top_pattern, c_test, acceptance);
+      match_pattern_1 (&root, info, pattern, acceptance);
       merge_into_state (s, &root);
     }
   else
-    match_pattern_1 (s, top_pattern, c_test, acceptance);
+    match_pattern_1 (s, info, pattern, acceptance);
 }
 
 /* Begin the output file.  */
@@ -4157,29 +4178,22 @@ write_header (void)
 #include \"config.h\"\n\
 #include \"system.h\"\n\
 #include \"coretypes.h\"\n\
-#include \"tm.h\"\n\
+#include \"backend.h\"\n\
+#include \"predict.h\"\n\
 #include \"rtl.h\"\n\
+#include \"memmodel.h\"\n\
 #include \"tm_p.h\"\n\
-#include \"hashtab.h\"\n\
-#include \"hash-set.h\"\n\
-#include \"vec.h\"\n\
-#include \"machmode.h\"\n\
-#include \"hard-reg-set.h\"\n\
-#include \"input.h\"\n\
-#include \"function.h\"\n\
+#include \"emit-rtl.h\"\n\
 #include \"insn-config.h\"\n\
 #include \"recog.h\"\n\
 #include \"output.h\"\n\
 #include \"flags.h\"\n\
-#include \"hard-reg-set.h\"\n\
-#include \"predict.h\"\n\
-#include \"basic-block.h\"\n\
+#include \"df.h\"\n\
 #include \"resource.h\"\n\
 #include \"diagnostic-core.h\"\n\
 #include \"reload.h\"\n\
 #include \"regs.h\"\n\
 #include \"tm-constrs.h\"\n\
-#include \"predict.h\"\n\
 \n");
 
   puts ("\n\
@@ -4232,6 +4246,9 @@ parameter_type_string (parameter::type_enum type)
     case parameter::INT:
       return "int";
 
+    case parameter::UINT:
+      return "unsigned int";
+
     case parameter::WIDE_INT:
       return "HOST_WIDE_INT";
     }
@@ -4278,7 +4295,7 @@ get_failure_return (routine_type type)
 
     case SPLIT:
     case PEEPHOLE2:
-      return "NULL_RTX";
+      return "NULL";
     }
   gcc_unreachable ();
 }
@@ -4320,7 +4337,7 @@ static bool
 terminal_pattern_p (decision *d, unsigned int *base_out,
                    unsigned int *count_out)
 {
-  if (d->test.kind != test::PATTERN)
+  if (d->test.kind != rtx_test::PATTERN)
     return false;
   unsigned int base = 0;
   unsigned int count = 0;
@@ -4329,7 +4346,7 @@ terminal_pattern_p (decision *d, unsigned int *base_out,
       if (trans->is_param || trans->labels.length () != 1)
        return false;
       decision *subd = trans->to->singleton ();
-      if (!subd || subd->test.kind != test::ACCEPT)
+      if (!subd || subd->test.kind != rtx_test::ACCEPT)
        return false;
       unsigned int this_base = (subd->test.u.acceptance.u.full.code
                                - trans->labels[0]);
@@ -4348,7 +4365,7 @@ terminal_pattern_p (decision *d, unsigned int *base_out,
    already available in state OS.  */
 
 static bool
-test_position_available_p (output_state *os, const test &test)
+test_position_available_p (output_state *os, const rtx_test &test)
 {
   return (!test.pos
          || test.pos_operand >= 0
@@ -4451,6 +4468,10 @@ print_parameter_value (const parameter &param)
        printf ("%d", (int) param.value);
        break;
 
+      case parameter::UINT:
+       printf ("%u", (unsigned int) param.value);
+       break;
+
       case parameter::WIDE_INT:
        print_host_wide_int (param.value);
        break;
@@ -4460,7 +4481,7 @@ print_parameter_value (const parameter &param)
 /* Print the C expression for the rtx tested by TEST.  */
 
 static void
-print_test_rtx (output_state *os, const test &test)
+print_test_rtx (output_state *os, const rtx_test &test)
 {
   if (test.pos_operand >= 0)
     printf ("operands[%d]", test.pos_operand);
@@ -4471,41 +4492,47 @@ print_test_rtx (output_state *os, const test &test)
 /* Print the C expression for non-boolean test TEST.  */
 
 static void
-print_nonbool_test (output_state *os, const test &test)
+print_nonbool_test (output_state *os, const rtx_test &test)
 {
   switch (test.kind)
     {
-    case test::CODE:
+    case rtx_test::CODE:
       printf ("GET_CODE (");
       print_test_rtx (os, test);
       printf (")");
       break;
 
-    case test::MODE:
+    case rtx_test::MODE:
       printf ("GET_MODE (");
       print_test_rtx (os, test);
       printf (")");
       break;
 
-    case test::VECLEN:
+    case rtx_test::VECLEN:
       printf ("XVECLEN (");
       print_test_rtx (os, test);
       printf (", 0)");
       break;
 
-    case test::INT_FIELD:
+    case rtx_test::INT_FIELD:
       printf ("XINT (");
       print_test_rtx (os, test);
       printf (", %d)", test.u.opno);
       break;
 
-    case test::WIDE_INT_FIELD:
+    case rtx_test::REGNO_FIELD:
+      printf ("REGNO (");
+      print_test_rtx (os, test);
+      printf (")");
+      break;
+
+    case rtx_test::WIDE_INT_FIELD:
       printf ("XWINT (");
       print_test_rtx (os, test);
       printf (", %d)", test.u.opno);
       break;
 
-    case test::PATTERN:
+    case rtx_test::PATTERN:
       {
        pattern_routine *routine = test.u.pattern->routine;
        printf ("pattern%d (", routine->pattern_id);
@@ -4535,15 +4562,15 @@ print_nonbool_test (output_state *os, const test &test)
        break;
       }
 
-    case test::PEEP2_COUNT:
-    case test::VECLEN_GE:
-    case test::SAVED_CONST_INT:
-    case test::DUPLICATE:
-    case test::PREDICATE:
-    case test::SET_OP:
-    case test::HAVE_NUM_CLOBBERS:
-    case test::C_TEST:
-    case test::ACCEPT:
+    case rtx_test::PEEP2_COUNT:
+    case rtx_test::VECLEN_GE:
+    case rtx_test::SAVED_CONST_INT:
+    case rtx_test::DUPLICATE:
+    case rtx_test::PREDICATE:
+    case rtx_test::SET_OP:
+    case rtx_test::HAVE_NUM_CLOBBERS:
+    case rtx_test::C_TEST:
+    case rtx_test::ACCEPT:
       gcc_unreachable ();
     }
 }
@@ -4552,7 +4579,7 @@ print_nonbool_test (output_state *os, const test &test)
    decision performs TEST.  Print the C code for the label.  */
 
 static void
-print_label_value (const test &test, bool is_param, uint64_t value)
+print_label_value (const rtx_test &test, bool is_param, uint64_t value)
 {
   print_parameter_value (parameter (transition_parameter_type (test.kind),
                                    is_param, value));
@@ -4563,24 +4590,25 @@ print_label_value (const test &test, bool is_param, uint64_t value)
    Test for inequality if INVERT_P, otherwise test for equality.  */
 
 static void
-print_test (output_state *os, const test &test, bool is_param, uint64_t value,
-           bool invert_p)
+print_test (output_state *os, const rtx_test &test, bool is_param,
+           uint64_t value, bool invert_p)
 {
   switch (test.kind)
     {
       /* Handle the non-boolean TESTs.  */
-    case test::CODE:
-    case test::MODE:
-    case test::VECLEN:
-    case test::INT_FIELD:
-    case test::WIDE_INT_FIELD:
-    case test::PATTERN:
+    case rtx_test::CODE:
+    case rtx_test::MODE:
+    case rtx_test::VECLEN:
+    case rtx_test::REGNO_FIELD:
+    case rtx_test::INT_FIELD:
+    case rtx_test::WIDE_INT_FIELD:
+    case rtx_test::PATTERN:
       print_nonbool_test (os, test);
       printf (" %s ", invert_p ? "!=" : "==");
       print_label_value (test, is_param, value);
       break;
 
-    case test::SAVED_CONST_INT:
+    case rtx_test::SAVED_CONST_INT:
       gcc_assert (!is_param && value == 1);
       print_test_rtx (os, test);
       printf (" %s const_int_rtx[MAX_SAVED_CONST_INT + ",
@@ -4591,20 +4619,20 @@ print_test (output_state *os, const test &test, bool is_param, uint64_t value,
       printf ("]");
       break;
 
-    case test::PEEP2_COUNT:
+    case rtx_test::PEEP2_COUNT:
       gcc_assert (!is_param && value == 1);
       printf ("peep2_current_count %s %d", invert_p ? "<" : ">=",
              test.u.min_len);
       break;
 
-    case test::VECLEN_GE:
+    case rtx_test::VECLEN_GE:
       gcc_assert (!is_param && value == 1);
       printf ("XVECLEN (");
       print_test_rtx (os, test);
       printf (", 0) %s %d", invert_p ? "<" : ">=", test.u.min_len);
       break;
 
-    case test::PREDICATE:
+    case rtx_test::PREDICATE:
       gcc_assert (!is_param && value == 1);
       printf ("%s%s (", invert_p ? "!" : "", test.u.predicate.data->name);
       print_test_rtx (os, test);
@@ -4615,27 +4643,27 @@ print_test (output_state *os, const test &test, bool is_param, uint64_t value,
       printf (")");
       break;
 
-    case test::DUPLICATE:
+    case rtx_test::DUPLICATE:
       gcc_assert (!is_param && value == 1);
       printf ("%srtx_equal_p (", invert_p ? "!" : "");
       print_test_rtx (os, test);
       printf (", operands[%d])", test.u.opno);
       break;
 
-    case test::HAVE_NUM_CLOBBERS:
+    case rtx_test::HAVE_NUM_CLOBBERS:
       gcc_assert (!is_param && value == 1);
       printf ("pnum_clobbers %s NULL", invert_p ? "==" : "!=");
       break;
 
-    case test::C_TEST:
+    case rtx_test::C_TEST:
       gcc_assert (!is_param && value == 1);
       if (invert_p)
        printf ("!");
-      print_c_condition (test.u.string);
+      rtx_reader_ptr->print_c_condition (test.u.string);
       break;
 
-    case test::ACCEPT:
-    case test::SET_OP:
+    case rtx_test::ACCEPT:
+    case rtx_test::SET_OP:
       gcc_unreachable ();
     }
 }
@@ -4811,9 +4839,9 @@ print_decision (output_state *os, decision *d, unsigned int indent,
          return ES_FALLTHROUGH;
        }
     }
-  else if (d->test.kind == test::ACCEPT)
+  else if (d->test.kind == rtx_test::ACCEPT)
     return print_acceptance (d->test.u.acceptance, indent, is_final);
-  else if (d->test.kind == test::SET_OP)
+  else if (d->test.kind == rtx_test::SET_OP)
     {
       printf_indent (indent, "operands[%d] = ", d->test.u.opno);
       print_test_rtx (os, d->test);
@@ -4842,8 +4870,8 @@ print_decision (output_state *os, decision *d, unsigned int indent,
        {
          d = trans->to->singleton ();
          if (!d
-             || d->test.kind == test::ACCEPT
-             || d->test.kind == test::SET_OP
+             || d->test.kind == rtx_test::ACCEPT
+             || d->test.kind == rtx_test::SET_OP
              || !d->if_statement_p (&label)
              || !test_position_available_p (os, d->test))
            break;
@@ -4868,7 +4896,7 @@ print_decision (output_state *os, decision *d, unsigned int indent,
          return print_state (os, to, indent, is_final);
        }
       else if (to->singleton ()
-              && to->first->test.kind == test::ACCEPT
+              && to->first->test.kind == rtx_test::ACCEPT
               && single_statement_p (to->first->test.u.acceptance))
        {
          /* The target of the transition is a simple "return" statement.
@@ -5021,7 +5049,7 @@ print_subroutine_start (output_state *os, state *s, position *root)
   if (os->type == SUBPATTERN || os->type == RECOG)
     printf ("  int res ATTRIBUTE_UNUSED;\n");
   else
-    printf ("  rtx res ATTRIBUTE_UNUSED;\n");
+    printf ("  rtx_insn *res ATTRIBUTE_UNUSED;\n");
 }
 
 /* Output the definition of pattern routine ROUTINE.  */
@@ -5071,11 +5099,6 @@ print_pattern (output_state *os, pattern_routine *routine)
 static void
 print_subroutine (output_state *os, state *s, int proc_id)
 {
-  /* For now, the top-level functions take a plain "rtx", and perform a
-     checked cast to "rtx_insn *" for use throughout the rest of the
-     function and the code it calls.  */
-  const char *insn_param
-    = proc_id > 0 ? "rtx_insn *insn" : "rtx uncast_insn";
   printf ("\n");
   switch (os->type)
     {
@@ -5088,35 +5111,32 @@ print_subroutine (output_state *os, state *s, int proc_id)
       else
        printf ("int\nrecog");
       printf (" (rtx x1 ATTRIBUTE_UNUSED,\n"
-             "\t%s ATTRIBUTE_UNUSED,\n"
-             "\tint *pnum_clobbers ATTRIBUTE_UNUSED)\n", insn_param);
+             "\trtx_insn *insn ATTRIBUTE_UNUSED,\n"
+             "\tint *pnum_clobbers ATTRIBUTE_UNUSED)\n");
       break;
 
     case SPLIT:
       if (proc_id)
-       printf ("static rtx\nsplit_%d", proc_id);
+       printf ("static rtx_insn *\nsplit_%d", proc_id);
       else
-       printf ("rtx\nsplit_insns");
-      printf (" (rtx x1 ATTRIBUTE_UNUSED, %s ATTRIBUTE_UNUSED)\n",
-             insn_param);
+       printf ("rtx_insn *\nsplit_insns");
+      printf (" (rtx x1 ATTRIBUTE_UNUSED, rtx_insn *insn ATTRIBUTE_UNUSED)\n");
       break;
 
     case PEEPHOLE2:
       if (proc_id)
-       printf ("static rtx\npeephole2_%d", proc_id);
+       printf ("static rtx_insn *\npeephole2_%d", proc_id);
       else
-       printf ("rtx\npeephole2_insns");
+       printf ("rtx_insn *\npeephole2_insns");
       printf (" (rtx x1 ATTRIBUTE_UNUSED,\n"
-             "\t%s ATTRIBUTE_UNUSED,\n"
-             "\tint *pmatch_len_ ATTRIBUTE_UNUSED)\n", insn_param);
+             "\trtx_insn *insn ATTRIBUTE_UNUSED,\n"
+             "\tint *pmatch_len_ ATTRIBUTE_UNUSED)\n");
       break;
     }
   print_subroutine_start (os, s, &root_pos);
   if (proc_id == 0)
     {
-      printf ("  recog_data.insn = NULL_RTX;\n");
-      printf ("  rtx_insn *insn ATTRIBUTE_UNUSED;\n");
-      printf ("  insn = safe_as_a <rtx_insn *> (uncast_insn);\n");
+      printf ("  recog_data.insn = NULL;\n");
     }
   print_state (os, s, 2, true);
   printf ("}\n");
@@ -5145,20 +5165,29 @@ print_subroutine_group (output_state *os, routine_type type, state *root)
   print_subroutine (os, root, 0);
 }
 
-/* Return the rtx pattern specified by the list of rtxes in a
-   define_insn or define_split.  */
+/* Return the rtx pattern for the list of rtxes in a define_peephole2.  */
 
 static rtx
-add_implicit_parallel (rtvec vec)
+get_peephole2_pattern (md_rtx_info *info)
 {
-  if (GET_NUM_ELEM (vec) == 1)
-    return RTVEC_ELT (vec, 0);
-  else
+  int i, j;
+  rtvec vec = XVEC (info->def, 0);
+  rtx pattern = rtx_alloc (SEQUENCE);
+  XVEC (pattern, 0) = rtvec_alloc (GET_NUM_ELEM (vec));
+  for (i = j = 0; i < GET_NUM_ELEM (vec); i++)
     {
-      rtx pattern = rtx_alloc (PARALLEL);
-      XVEC (pattern, 0) = vec;
-      return pattern;
+      rtx x = RTVEC_ELT (vec, i);
+      /* Ignore scratch register requirements.  */
+      if (GET_CODE (x) != MATCH_SCRATCH && GET_CODE (x) != MATCH_DUP)
+       {
+         XVECEXP (pattern, 0, j) = x;
+         j++;
+       }
     }
+  XVECLEN (pattern, 0) = j;
+  if (j == 0)
+    error_at (info->loc, "empty define_peephole2");
+  return pattern;
 }
 
 /* Return true if *PATTERN_PTR is a PARALLEL in which at least one trailing
@@ -5205,9 +5234,8 @@ remove_clobbers (acceptance_type *acceptance_ptr, rtx *pattern_ptr)
 }
 
 int
-main (int argc, char **argv)
+main (int argc, const char **argv)
 {
-  rtx desc;
   state insn_root, split_root, peephole2_root;
 
   progname = "genrecog";
@@ -5215,61 +5243,61 @@ main (int argc, char **argv)
   if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
-  next_insn_code = 0;
-
   write_header ();
 
   /* Read the machine description.  */
 
-  while (1)
+  md_rtx_info info;
+  while (read_md_rtx (&info))
     {
-      desc = read_md_rtx (&pattern_lineno, &next_insn_code);
-      if (desc == NULL)
-       break;
-
-      rtx pattern;
+      rtx def = info.def;
 
       acceptance_type acceptance;
       acceptance.partial_p = false;
-      acceptance.u.full.code = next_insn_code;
+      acceptance.u.full.code = info.index;
 
-      switch (GET_CODE (desc))
+      rtx pattern;
+      switch (GET_CODE (def))
        {
        case DEFINE_INSN:
          {
            /* Match the instruction in the original .md form.  */
-           pattern = add_implicit_parallel (XVEC (desc, 1));
            acceptance.type = RECOG;
            acceptance.u.full.u.num_clobbers = 0;
-           match_pattern (&insn_root, pattern, XSTR (desc, 2), acceptance);
+           pattern = add_implicit_parallel (XVEC (def, 1));
+           validate_pattern (pattern, &info, NULL_RTX, 0);
+           match_pattern (&insn_root, &info, pattern, acceptance);
 
            /* If the pattern is a PARALLEL with trailing CLOBBERs,
               allow recog_for_combine to match without the clobbers.  */
            if (GET_CODE (pattern) == PARALLEL
                && remove_clobbers (&acceptance, &pattern))
-             match_pattern (&insn_root, pattern, XSTR (desc, 2), acceptance);
+             match_pattern (&insn_root, &info, pattern, acceptance);
            break;
          }
 
        case DEFINE_SPLIT:
          acceptance.type = SPLIT;
-         pattern = add_implicit_parallel (XVEC (desc, 0));
-         match_pattern (&split_root, pattern, XSTR (desc, 1), acceptance);
+         pattern = add_implicit_parallel (XVEC (def, 0));
+         validate_pattern (pattern, &info, NULL_RTX, 0);
+         match_pattern (&split_root, &info, pattern, acceptance);
 
          /* Declare the gen_split routine that we'll call if the
             pattern matches.  The definition comes from insn-emit.c.  */
-         printf ("extern rtx gen_split_%d (rtx_insn *, rtx *);\n",
-                 next_insn_code);
+         printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n",
+                 info.index);
          break;
 
        case DEFINE_PEEPHOLE2:
          acceptance.type = PEEPHOLE2;
-         match_pattern (&peephole2_root, desc, XSTR (desc, 1), acceptance);
+         pattern = get_peephole2_pattern (&info);
+         validate_pattern (pattern, &info, NULL_RTX, 0);
+         match_pattern (&peephole2_root, &info, pattern, acceptance);
 
          /* Declare the gen_peephole2 routine that we'll call if the
             pattern matches.  The definition comes from insn-emit.c.  */
-         printf ("extern rtx gen_peephole2_%d (rtx_insn *, rtx *);\n",
-                 next_insn_code);
+         printf ("extern rtx_insn *gen_peephole2_%d (rtx_insn *, rtx *);\n",
+                 info.index);
          break;
 
        default: