2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-18 05:40:23 +08:00

Amend match.pd syntax with force-simplified results

This adds a ! marker to result expressions that should simplify
(and if not fail the simplification).  This can for example be
used like

(simplify
  (plus (vec_cond:s @0 @1 @2) @3)
  (vec_cond @0 (plus! @1 @3) (plus! @2 @3)))

to make the simplification only apply in case both plus operations
in the result end up simplified to a simple operand.

2020-07-31  Richard Biener  <rguenther@suse.de>

	* genmatch.c (expr::force_leaf): Add and initialize.
	(expr::gen_transform): Honor force_leaf by passing
	NULL as sequence argument to maybe_push_res_to_seq.
	(parser::parse_expr): Allow ! marker on result expression
	operations.
	* doc/match-and-simplify.texi: Amend.
This commit is contained in:
Richard Biener 2020-07-31 14:24:26 +02:00
parent c89366b12f
commit 14c35be3bf
2 changed files with 31 additions and 3 deletions

@ -361,6 +361,21 @@ Usually the types of the generated result expressions are
determined from the context, but sometimes like in the above case
it is required that you specify them explicitely.
Another modifier for generated expressions is @code{!} which
tells the machinery to only consider the simplification in case
the marked expression simplified to a simple operand. Consider
for example
@smallexample
(simplify
(plus (vec_cond:s @@0 @@1 @@2) @@3)
(vec_cond @@0 (plus! @@1 @@3) (plus! @@2 @@3)))
@end smallexample
which moves the outer @code{plus} operation to the inner arms
of the @code{vec_cond} expression but only if the actual plus
operations both simplify.
As intermediate conversions are often optional there is a way to
avoid the need to repeat patterns both with and without such
conversions. Namely you can mark a conversion as being optional

@ -697,12 +697,13 @@ public:
expr (id_base *operation_, location_t loc, bool is_commutative_ = false)
: operand (OP_EXPR, loc), operation (operation_),
ops (vNULL), expr_type (NULL), is_commutative (is_commutative_),
is_generic (false), force_single_use (false), opt_grp (0) {}
is_generic (false), force_single_use (false), force_leaf (false),
opt_grp (0) {}
expr (expr *e)
: operand (OP_EXPR, e->location), operation (e->operation),
ops (vNULL), expr_type (e->expr_type), is_commutative (e->is_commutative),
is_generic (e->is_generic), force_single_use (e->force_single_use),
opt_grp (e->opt_grp) {}
force_leaf (e->force_leaf), opt_grp (e->opt_grp) {}
void append_op (operand *op) { ops.safe_push (op); }
/* The operator and its operands. */
id_base *operation;
@ -717,6 +718,9 @@ public:
/* Whether pushing any stmt to the sequence should be conditional
on this expression having a single-use. */
bool force_single_use;
/* Whether in the result expression this should be a leaf node
with any children simplified down to simple operands. */
bool force_leaf;
/* If non-zero, the group for optional handling. */
unsigned char opt_grp;
virtual void gen_transform (FILE *f, int, const char *, bool, int,
@ -2520,7 +2524,8 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple,
fprintf (f, ");\n");
fprintf_indent (f, indent, "tem_op.resimplify (lseq, valueize);\n");
fprintf_indent (f, indent,
"_r%d = maybe_push_res_to_seq (&tem_op, lseq);\n", depth);
"_r%d = maybe_push_res_to_seq (&tem_op, %s);\n", depth,
!force_leaf ? "lseq" : "NULL");
fprintf_indent (f, indent,
"if (!_r%d) return false;\n",
depth);
@ -4240,6 +4245,14 @@ parser::parse_expr ()
bool force_capture = false;
const char *expr_type = NULL;
if (!parsing_match_operand
&& token->type == CPP_NOT
&& !(token->flags & PREV_WHITE))
{
eat_token (CPP_NOT);
e->force_leaf = true;
}
if (token->type == CPP_COLON
&& !(token->flags & PREV_WHITE))
{