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  <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
This commit is contained in:
Richard Sandiford 2019-07-12 07:54:23 +00:00 committed by Richard Sandiford
parent 1fdd6f0412
commit d281492de8
5 changed files with 89 additions and 54 deletions

View 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.

View 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

View 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

View 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));
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

View 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);