Commit d281492d by Richard Sandiford Committed by Richard Sandiford

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
parent 1fdd6f04
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> 2019-07-12 Jakub Jelinek <jakub@redhat.com>
* tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER. * tree-core.h (enum omp_clause_code): Add OMP_CLAUSE_ORDER.
......
...@@ -11381,4 +11381,13 @@ name and same types of iterator. For example: ...@@ -11381,4 +11381,13 @@ name and same types of iterator. For example:
would produce a single set of functions that handles both would produce a single set of functions that handles both
@code{INTEGER_MODES} and @code{FLOAT_MODES}. @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 @end ifset
...@@ -811,42 +811,45 @@ handle_overloaded_code_for (overloaded_name *oname) ...@@ -811,42 +811,45 @@ handle_overloaded_code_for (overloaded_name *oname)
static void static void
handle_overloaded_gen (overloaded_name *oname) handle_overloaded_gen (overloaded_name *oname)
{ {
unsigned HOST_WIDE_INT seen = 0;
/* All patterns must have the same number of operands. */ /* 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; for (overloaded_instance *instance = oname->first_instance->next;
instance; instance = instance->next) instance; instance = instance->next)
{ {
pattern_stats stats2; pattern_stats stats;
get_pattern_stats (&stats2, XVEC (instance->insn, 1)); get_pattern_stats (&stats, XVEC (instance->insn, 1));
if (stats.num_generator_args != stats2.num_generator_args) unsigned HOST_WIDE_INT mask
fatal_at (get_file_location (instance->insn), = HOST_WIDE_INT_1U << stats.num_generator_args;
"inconsistent number of operands for '%s'; " if (seen & mask)
"this instance has %d, but previous instances had %d", continue;
oname->name, stats2.num_generator_args,
stats.num_generator_args); 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 int
......
...@@ -134,31 +134,43 @@ handle_overloaded_code_for (FILE *file, overloaded_name *oname) ...@@ -134,31 +134,43 @@ handle_overloaded_code_for (FILE *file, overloaded_name *oname)
static void static void
handle_overloaded_gen (FILE *file, overloaded_name *oname) handle_overloaded_gen (FILE *file, overloaded_name *oname)
{ {
pattern_stats stats; unsigned HOST_WIDE_INT seen = 0;
get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1)); for (overloaded_instance *instance = oname->first_instance->next;
instance; instance = instance->next)
fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name); {
for (unsigned int i = 0; i < oname->arg_types.length (); ++i) pattern_stats stats;
fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]); get_pattern_stats (&stats, XVEC (instance->insn, 1));
for (int i = 0; i < stats.num_generator_args; ++i) unsigned HOST_WIDE_INT mask
fprintf (file, ", rtx"); = HOST_WIDE_INT_1U << stats.num_generator_args;
fprintf (file, ");\n"); if (seen & mask)
continue;
fprintf (file, "inline rtx\ngen_%s (", oname->name);
for (unsigned int i = 0; i < oname->arg_types.length (); ++i) seen |= mask;
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, "\nextern rtx maybe_gen_%s (", oname->name);
fprintf (file, ", rtx x%d", i); for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name); fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
for (unsigned int i = 0; i < oname->arg_types.length (); ++i) for (int i = 0; i < stats.num_generator_args; ++i)
fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i); fprintf (file, ", rtx");
for (int i = 0; i < stats.num_generator_args; ++i) fprintf (file, ");\n");
fprintf (file, ", x%d", i);
fprintf (file, fprintf (file, "inline rtx\ngen_%s (", oname->name);
");\n" for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
" gcc_assert (res);\n" fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ",
" return res;\n" oname->arg_types[i], i);
"}\n"); 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 int
......
...@@ -500,12 +500,14 @@ replace_operands_with_dups (rtx x) ...@@ -500,12 +500,14 @@ replace_operands_with_dups (rtx x)
{ {
newx = rtx_alloc (MATCH_DUP); newx = rtx_alloc (MATCH_DUP);
XINT (newx, 0) = XINT (x, 0); XINT (newx, 0) = XINT (x, 0);
x = newx;
} }
else if (GET_CODE (x) == MATCH_OPERATOR) else if (GET_CODE (x) == MATCH_OPERATOR)
{ {
newx = rtx_alloc (MATCH_OP_DUP); newx = rtx_alloc (MATCH_OP_DUP);
XINT (newx, 0) = XINT (x, 0); XINT (newx, 0) = XINT (x, 0);
XVEC (newx, 1) = XVEC (x, 2); XVEC (newx, 1) = XVEC (x, 2);
x = newx;
} }
else else
newx = shallow_copy_rtx (x); newx = shallow_copy_rtx (x);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment