Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	2019-07-03 20:50:42.350350342 +0100
+++ gcc/doc/md.texi	2019-07-12 08:53:37.501727954 +0100
@@ -11381,4 +11381,13 @@ name and same types of iterator.  For ex
 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: gcc/genemit.c
===================================================================
--- gcc/genemit.c	2019-03-08 18:14:27.285004225 +0000
+++ gcc/genemit.c	2019-07-12 08:53:37.501727954 +0100
@@ -811,42 +811,45 @@ handle_overloaded_code_for (overloaded_n
 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");
+      /* 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");
+      /* 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");
+    }
 }
 
 int
Index: gcc/genopinit.c
===================================================================
--- gcc/genopinit.c	2019-03-08 18:14:26.505007190 +0000
+++ gcc/genopinit.c	2019-07-12 08:53:37.501727954 +0100
@@ -134,31 +134,43 @@ handle_overloaded_code_for (FILE *file,
 static void
 handle_overloaded_gen (FILE *file, overloaded_name *oname)
 {
-  pattern_stats stats;
-  get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
+  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;
 
-  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");
+      seen |= mask;
 
-  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");
+      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: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2019-07-10 19:41:21.627936214 +0100
+++ gcc/gensupport.c	2019-07-12 08:53:37.505727920 +0100
@@ -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);
