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. Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu. Applied as r273432. Richard 2019-07-12 Richard Sandiford <richard.sandif...@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. ------------------------------------------------------------------------------ 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);