From d281492de84960b5885f88fffeeb226650f5141d Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Fri, 12 Jul 2019 07:54:23 +0000 Subject: [PATCH] Support multiple operand counts for .md @ patterns 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 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 | 9 +++++++ gcc/doc/md.texi | 9 +++++++ gcc/genemit.c | 65 +++++++++++++++++++++++++----------------------- gcc/genopinit.c | 62 ++++++++++++++++++++++++++------------------- gcc/gensupport.c | 2 ++ 5 files changed, 91 insertions(+), 56 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34fb0da4846..0894db7f0d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-07-12 Richard Sandiford + + * 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 * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index b1fcc38d76b..af216da6768 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -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 diff --git a/gcc/genemit.c b/gcc/genemit.c index 83f86a35c57..3ff819720ec 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -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 diff --git a/gcc/genopinit.c b/gcc/genopinit.c index ea4c3ce0186..1dd1d82d048 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -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 diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 0ad9995b642..1aab7119901 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -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); -- 2.30.2