Support multiple operand counts for .md @ patterns
authorRichard Sandiford <richard.sandiford@arm.com>
Fri, 12 Jul 2019 07:54:23 +0000 (07:54 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Fri, 12 Jul 2019 07:54:23 +0000 (07:54 +0000)
This patch extends the support for "@..." pattern names so that
the patterns can have different numbers of operands.  This allows
things like binary and ternary operations to be handled in a
consistent way, a bit like optabs.  The generators assert that
the number of operands passed is correct for the underlying
instruction.

Also, replace_operands_with_dups iterated over the old rtx format
even after having decided to do a replacement, which broke with
match_operator.

2019-07-12  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* doc/md.texi: Document that @ patterns can have different
numbers of operands.
* genemit.c (handle_overloaded_gen): Handle this case.
* genopinit.c (handle_overloaded_gen): Likewise.
* gensupport.c (replace_operands_with_dups): Iterate over
the new rtx's format rather than the old one's.

From-SVN: r273432

gcc/ChangeLog
gcc/doc/md.texi
gcc/genemit.c
gcc/genopinit.c
gcc/gensupport.c

index 34fb0da484617bad143bd7e8bc54c5e866c5a281..0894db7f0d30a80551926841e6db98766a89dac8 100644 (file)
@@ -1,3 +1,12 @@
+2019-07-12  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * doc/md.texi: Document that @ patterns can have different
+       numbers of operands.
+       * genemit.c (handle_overloaded_gen): Handle this case.
+       * genopinit.c (handle_overloaded_gen): Likewise.
+       * gensupport.c (replace_operands_with_dups): Iterate over
+       the new rtx's format rather than the old one's.
+
 2019-07-12  Jakub Jelinek  <jakub@redhat.com>
 
        * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER.
index b1fcc38d76bcdd3ddda9c346124671f94ee6bf8e..af216da6768807973215e9761d54da5fee2970dd 100644 (file)
@@ -11381,4 +11381,13 @@ name and same types of iterator.  For example:
 would produce a single set of functions that handles both
 @code{INTEGER_MODES} and @code{FLOAT_MODES}.
 
+It is also possible for these @samp{@@} patterns to have different
+numbers of operands from each other.  For example, patterns with
+a binary rtl code might take three operands (one output and two inputs)
+while patterns with a ternary rtl code might take four operands (one
+output and three inputs).  This combination would produce separate
+@samp{maybe_gen_@var{name}} and @samp{gen_@var{name}} functions for
+each operand count, but it would still produce a single
+@samp{maybe_code_for_@var{name}} and a single @samp{code_for_@var{name}}.
+
 @end ifset
index 83f86a35c57b7d4d9b6bb5d84dcefff5997594ee..3ff819720ec6d7d90e5407bf7065544c5c65d84f 100644 (file)
@@ -811,42 +811,45 @@ handle_overloaded_code_for (overloaded_name *oname)
 static void
 handle_overloaded_gen (overloaded_name *oname)
 {
+  unsigned HOST_WIDE_INT seen = 0;
   /* All patterns must have the same number of operands.  */
-  pattern_stats stats;
-  get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
   for (overloaded_instance *instance = oname->first_instance->next;
        instance; instance = instance->next)
     {
-      pattern_stats stats2;
-      get_pattern_stats (&stats2, XVEC (instance->insn, 1));
-      if (stats.num_generator_args != stats2.num_generator_args)
-       fatal_at (get_file_location (instance->insn),
-                 "inconsistent number of operands for '%s'; "
-                 "this instance has %d, but previous instances had %d",
-                 oname->name, stats2.num_generator_args,
-                 stats.num_generator_args);
+      pattern_stats stats;
+      get_pattern_stats (&stats, XVEC (instance->insn, 1));
+      unsigned HOST_WIDE_INT mask
+       = HOST_WIDE_INT_1U << stats.num_generator_args;
+      if (seen & mask)
+       continue;
+
+      seen |= mask;
+
+      /* Print the function prototype.  */
+      printf ("\nrtx\nmaybe_gen_%s (", oname->name);
+      print_overload_arguments (oname);
+      for (int i = 0; i < stats.num_generator_args; ++i)
+       printf (", rtx x%d", i);
+      printf (")\n{\n");
+
+      /* Use maybe_code_for_*, instead of duplicating the selection
+        logic here.  */
+      printf ("  insn_code code = maybe_code_for_%s (", oname->name);
+      for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+       printf ("%sarg%d", i == 0 ? "" : ", ", i);
+      printf (");\n"
+             "  if (code != CODE_FOR_nothing)\n"
+             "    {\n"
+             "      gcc_assert (insn_data[code].n_generator_args == %d);\n"
+             "      return GEN_FCN (code) (", stats.num_generator_args);
+      for (int i = 0; i < stats.num_generator_args; ++i)
+       printf ("%sx%d", i == 0 ? "" : ", ", i);
+      printf (");\n"
+             "    }\n"
+             "  else\n"
+             "    return NULL_RTX;\n"
+             "}\n");
     }
-
-  /* Print the function prototype.  */
-  printf ("\nrtx\nmaybe_gen_%s (", oname->name);
-  print_overload_arguments (oname);
-  for (int i = 0; i < stats.num_generator_args; ++i)
-    printf (", rtx x%d", i);
-  printf (")\n{\n");
-
-  /* Use maybe_code_for_*, instead of duplicating the selection logic here.  */
-  printf ("  insn_code code = maybe_code_for_%s (", oname->name);
-  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
-    printf ("%sarg%d", i == 0 ? "" : ", ", i);
-  printf (");\n"
-         "  if (code != CODE_FOR_nothing)\n"
-         "    return GEN_FCN (code) (");
-  for (int i = 0; i < stats.num_generator_args; ++i)
-    printf ("%sx%d", i == 0 ? "" : ", ", i);
-  printf (");\n"
-         "  else\n"
-         "    return NULL_RTX;\n"
-         "}\n");
 }
 
 int
index ea4c3ce0186fb23e4712a357cc452c4a45fba818..1dd1d82d0485c5d11b4bc9085bf99ccb8bbb992b 100644 (file)
@@ -134,31 +134,43 @@ handle_overloaded_code_for (FILE *file, overloaded_name *oname)
 static void
 handle_overloaded_gen (FILE *file, overloaded_name *oname)
 {
-  pattern_stats stats;
-  get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
-
-  fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
-  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
-    fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
-  for (int i = 0; i < stats.num_generator_args; ++i)
-    fprintf (file, ", rtx");
-  fprintf (file, ");\n");
-
-  fprintf (file, "inline rtx\ngen_%s (", oname->name);
-  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
-    fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
-  for (int i = 0; i < stats.num_generator_args; ++i)
-    fprintf (file, ", rtx x%d", i);
-  fprintf (file, ")\n{\n  rtx res = maybe_gen_%s (", oname->name);
-  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
-    fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
-  for (int i = 0; i < stats.num_generator_args; ++i)
-    fprintf (file, ", x%d", i);
-  fprintf (file,
-          ");\n"
-          "  gcc_assert (res);\n"
-          "  return res;\n"
-          "}\n");
+  unsigned HOST_WIDE_INT seen = 0;
+  for (overloaded_instance *instance = oname->first_instance->next;
+       instance; instance = instance->next)
+    {
+      pattern_stats stats;
+      get_pattern_stats (&stats, XVEC (instance->insn, 1));
+      unsigned HOST_WIDE_INT mask
+       = HOST_WIDE_INT_1U << stats.num_generator_args;
+      if (seen & mask)
+       continue;
+
+      seen |= mask;
+
+      fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
+      for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+       fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
+      for (int i = 0; i < stats.num_generator_args; ++i)
+       fprintf (file, ", rtx");
+      fprintf (file, ");\n");
+
+      fprintf (file, "inline rtx\ngen_%s (", oname->name);
+      for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+       fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ",
+                oname->arg_types[i], i);
+      for (int i = 0; i < stats.num_generator_args; ++i)
+       fprintf (file, ", rtx x%d", i);
+      fprintf (file, ")\n{\n  rtx res = maybe_gen_%s (", oname->name);
+      for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+       fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
+      for (int i = 0; i < stats.num_generator_args; ++i)
+       fprintf (file, ", x%d", i);
+      fprintf (file,
+              ");\n"
+              "  gcc_assert (res);\n"
+              "  return res;\n"
+              "}\n");
+    }
 }
 
 int
index 0ad9995b6422df458531139f17d3c8495460551d..1aab711990184346eda51391c01b37aeb35b7d73 100644 (file)
@@ -500,12 +500,14 @@ replace_operands_with_dups (rtx x)
     {
       newx = rtx_alloc (MATCH_DUP);
       XINT (newx, 0) = XINT (x, 0);
+      x = newx;
     }
   else if (GET_CODE (x) == MATCH_OPERATOR)
     {
       newx = rtx_alloc (MATCH_OP_DUP);
       XINT (newx, 0) = XINT (x, 0);
       XVEC (newx, 1) = XVEC (x, 2);
+      x = newx;
     }
   else
     newx = shallow_copy_rtx (x);