Thomas pointed out that, while I'd kept the code to validate patterns
for things like missing modes, the code wasn't being used.  Fixed with
the patch below.

I ended up reinstating the original code to create a single rtx
pattern for a define_peephole2 sequence, so that it could be
passed to validate_pattern as before.  One of the reasons I got
rid of the code originally was because I didn't like the idea of
a sequence of define_peephole2 instructions being put into a
PARALLEL -- there's nothing parallel about them, and it would be
easy to confuse the result with a "real" parallel in a define_insn
or define_split match.  I therefore changed it to use SEQUENCE instead.
(Not that it matters: nothing actually looks at the code.)

I also threw in a check for zero-length define_peephole2s while there.
This is enforced syntactically for other define_*s, but it's possible
to write a define_peephole2 that just asks for scratch registers and
doesn't actually match anything.

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


gcc/
        * genrecog.c (match_pattern_1): Expect the pattern to be a SEQUENCE
        for define_peephole2s.
        (get_peephole2_pattern): New function.
        (main): Use it.  Call validate_pattern.

Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c      2015-05-10 10:45:41.750134123 +0100
+++ gcc/genrecog.c      2015-05-10 10:45:41.746134173 +0100
@@ -4080,14 +4080,14 @@ match_pattern_2 (state *s, rtx top_patte
    (2) the rtx matches TOP_PATTERN and
    (3) C_TEST 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,
                 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;
@@ -4095,18 +4095,14 @@ match_pattern_1 (state *s, rtx top_patte
       for (int i = 0; i < XVECLEN (top_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, rtx_test::peep2_count (count + 1),
-                                 true, false);
-             s = match_pattern_2 (s, top_pattern, subpos, x);
-             subpos_ptr = &subpos->next;
-             count += 1;
-           }
+         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, top_pattern, subpos, x);
+         subpos_ptr = &subpos->next;
+         count += 1;
        }
       acceptance.u.full.u.match_len = count - 1;
     }
@@ -5165,6 +5161,30 @@ add_implicit_parallel (rtvec vec)
     }
 }
 
+/* Return the rtx pattern for the list of rtxes in a define_peephole2.  */
+
+static rtx
+get_peephole2_pattern (rtvec vec)
+{
+  int i, j;
+  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 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_with_line (pattern_lineno, "empty define_peephole2");
+  return pattern;
+}
+
 /* Return true if *PATTERN_PTR is a PARALLEL in which at least one trailing
    rtx can be added automatically by add_clobbers.  If so, update
    *ACCEPTANCE_PTR so that its num_clobbers field contains the number
@@ -5231,20 +5251,20 @@ main (int argc, char **argv)
       if (desc == NULL)
        break;
 
-      rtx pattern;
-
       acceptance_type acceptance;
       acceptance.partial_p = false;
       acceptance.u.full.code = next_insn_code;
 
+      rtx pattern;
       switch (GET_CODE (desc))
        {
        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;
+           pattern = add_implicit_parallel (XVEC (desc, 1));
+           validate_pattern (pattern, desc, NULL_RTX, 0);
            match_pattern (&insn_root, pattern, XSTR (desc, 2), acceptance);
 
            /* If the pattern is a PARALLEL with trailing CLOBBERs,
@@ -5258,6 +5278,7 @@ main (int argc, char **argv)
        case DEFINE_SPLIT:
          acceptance.type = SPLIT;
          pattern = add_implicit_parallel (XVEC (desc, 0));
+         validate_pattern (pattern, desc, NULL_RTX, 0);
          match_pattern (&split_root, pattern, XSTR (desc, 1), acceptance);
 
          /* Declare the gen_split routine that we'll call if the
@@ -5268,7 +5289,9 @@ main (int argc, char **argv)
 
        case DEFINE_PEEPHOLE2:
          acceptance.type = PEEPHOLE2;
-         match_pattern (&peephole2_root, desc, XSTR (desc, 1), acceptance);
+         pattern = get_peephole2_pattern (XVEC (desc, 0));
+         validate_pattern (pattern, desc, NULL_RTX, 0);
+         match_pattern (&peephole2_root, pattern, XSTR (desc, 1), acceptance);
 
          /* Declare the gen_peephole2 routine that we'll call if the
             pattern matches.  The definition comes from insn-emit.c.  */

Reply via email to