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:
parent
1fdd6f0412
commit
d281492de8
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user