* [PATCH][match-and-simplify] Get rid of some stmt expressions
@ 2014-06-03 13:15 Richard Biener
0 siblings, 0 replies; only message in thread
From: Richard Biener @ 2014-06-03 13:15 UTC (permalink / raw)
To: gcc-patches; +Cc: bilbotheelffriend
The following arranges for complex C-expressions (multi-stmt ones)
in the transform pattern to be outlined to a separate function.
This avoids the need for using stmt expressions which are not
necessarily supported by all C++ host compilers.
The patch doesn't address the stmt expressions being used by
the matching code generator - that will be rewritten anyways.
Lightly tested, I plan to install this tomorrow.
Note that this also gives way of re-numbering captures before
code generation so their number increases when for example
walking in pre-order. And it gives an easier possibility for
querying the largest capture number as well.
Richard.
2014-06-03 Richard Biener <rguenther@suse.de>
* genmatch.c (c_expr): Record cpp_tokens, the number of
stmts seen and a function identifier.
(c_expr::gen_gimple_transform): Generate textual form
from the token vector or a call to the outlined function.
(write_nary_simplifiers): Adjust.
(outline_c_exprs): New function.
(write_gimple): Call it.
(parse_c_expr): Record a cpp_token vector.
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c (revision 211131)
+++ gcc/genmatch.c (working copy)
@@ -190,9 +190,13 @@ struct expr : public operand
struct c_expr : public operand
{
- c_expr (const char *code_)
- : operand (OP_C_EXPR), code (code_) {}
- const char *code;
+ c_expr (cpp_reader *r_, vec<cpp_token> code_, unsigned nr_stmts_)
+ : operand (OP_C_EXPR), r (r_), code (code_),
+ nr_stmts (nr_stmts_), fname (NULL) {}
+ cpp_reader *r;
+ vec<cpp_token> code;
+ unsigned nr_stmts;
+ char *fname;
virtual void gen_gimple_match (FILE *, const char *, const char *) { gcc_unreachable (); }
virtual void gen_gimple_transform (FILE *f, const char *);
};
@@ -440,7 +444,47 @@ expr::gen_gimple_transform (FILE *f, con
void
c_expr::gen_gimple_transform (FILE *f, const char *)
{
- fputs (code, f);
+ /* If this expression has an outlined function variant, call it. */
+ if (fname)
+ {
+ fprintf (f, "%s (type, captures)", fname);
+ return;
+ }
+
+ /* All multi-stmt expressions should have been outlined. */
+ gcc_assert (nr_stmts <= 1);
+
+ for (unsigned i = 0; i < code.length (); ++i)
+ {
+ const cpp_token *token = &code[i];
+
+ /* Replace captures for code-gen. */
+ if (token->type == CPP_ATSIGN)
+ {
+ const cpp_token *n = &code[i+1];
+ if (n->type == CPP_NUMBER
+ && !(n->flags & PREV_WHITE))
+ {
+ if (token->flags & PREV_WHITE)
+ fputc (' ', f);
+ fprintf (f, "captures[%s]", n->val.str.text);
+ ++i;
+ continue;
+ }
+ }
+
+ /* Skip a single stmt delimiter. */
+ if (token->type == CPP_SEMICOLON
+ && nr_stmts == 1)
+ continue;
+
+ if (token->flags & PREV_WHITE)
+ fputc (' ', f);
+
+ /* Output the token as string. */
+ char *tk = (char *)cpp_token_as_text (r, token);
+ fputs (tk, f);
+ }
}
void
@@ -495,9 +539,9 @@ write_nary_simplifiers (FILE *f, vec<sim
}
if (s->ifexpr)
{
- fprintf (f, " if (!");
+ fprintf (f, " if (!(");
s->ifexpr->gen_gimple_transform (f, fail_label);
- fprintf (f, ") goto %s;", fail_label);
+ fprintf (f, ")) goto %s;", fail_label);
}
if (s->result->type == operand::OP_EXPR)
{
@@ -533,11 +577,82 @@ write_nary_simplifiers (FILE *f, vec<sim
}
static void
+outline_c_exprs (FILE *f, struct operand *op)
+{
+ if (op->type == operand::OP_C_EXPR)
+ {
+ c_expr *e = static_cast <c_expr *>(op);
+ static unsigned fnnr = 1;
+ if (e->nr_stmts > 1
+ && !e->fname)
+ {
+ e->fname = (char *)xmalloc (sizeof ("cexprfn") + 4);
+ sprintf (e->fname, "cexprfn%d", fnnr);
+ fprintf (f, "static tree cexprfn%d (tree type, tree *captures)\n",
+ fnnr);
+ fprintf (f, "{\n");
+ unsigned stmt_nr = 1;
+ for (unsigned i = 0; i < e->code.length (); ++i)
+ {
+ const cpp_token *token = &e->code[i];
+
+ /* Replace captures for code-gen. */
+ if (token->type == CPP_ATSIGN)
+ {
+ const cpp_token *n = &e->code[i+1];
+ if (n->type == CPP_NUMBER
+ && !(n->flags & PREV_WHITE))
+ {
+ if (token->flags & PREV_WHITE)
+ fputc (' ', f);
+ fprintf (f, "captures[%s]", n->val.str.text);
+ ++i;
+ continue;
+ }
+ }
+
+ if (token->flags & PREV_WHITE)
+ fputc (' ', f);
+
+ /* Output the token as string. */
+ char *tk = (char *)cpp_token_as_text (e->r, token);
+ fputs (tk, f);
+
+ if (token->type == CPP_SEMICOLON)
+ {
+ stmt_nr++;
+ if (stmt_nr == e->nr_stmts)
+ fputs ("\n return ", f);
+ }
+ }
+ fprintf (f, "\n}\n");
+ fnnr++;
+ }
+ }
+ else if (op->type == operand::OP_CAPTURE)
+ {
+ capture *c = static_cast <capture *>(op);
+ if (c->what)
+ outline_c_exprs (f, c->what);
+ }
+ else if (op->type == operand::OP_EXPR)
+ {
+ expr *e = static_cast <expr *>(op);
+ for (unsigned i = 0; i < e->ops.length (); ++i)
+ outline_c_exprs (f, e->ops[i]);
+ }
+}
+
+static void
write_gimple (FILE *f, vec<simplify *>& simplifiers)
{
/* Include the header instead of writing it awkwardly quoted here. */
fprintf (f, "#include \"gimple-match-head.c\"\n\n");
+ /* Outline complex C expressions to helper functions. */
+ for (unsigned i = 0; i < simplifiers.length (); ++i)
+ outline_c_exprs (stdout, simplifiers[i]->result);
+
write_nary_simplifiers (f, simplifiers, 1);
write_nary_simplifiers (f, simplifiers, 2);
write_nary_simplifiers (f, simplifiers, 3);
@@ -716,18 +831,13 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
const cpp_token *token;
cpp_ttype end;
unsigned opencnt;
- char *code;
+ vec<cpp_token> code = vNULL;
+ unsigned nr_stmts = 0;
eat_token (r, start);
if (start == CPP_OPEN_PAREN)
- {
- code = xstrdup ("(");
- end = CPP_CLOSE_PAREN;
- }
+ end = CPP_CLOSE_PAREN;
else if (start == CPP_OPEN_BRACE)
- {
- code = xstrdup ("({");
- end = CPP_CLOSE_BRACE;
- }
+ end = CPP_CLOSE_BRACE;
else
gcc_unreachable ();
opencnt = 1;
@@ -735,24 +845,6 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
{
token = next (r);
- /* Replace captures for code-gen. */
- if (token->type == CPP_ATSIGN)
- {
- const cpp_token *n = peek (r);
- if (n->type == CPP_NUMBER
- && !(n->flags & PREV_WHITE))
- {
- code = (char *)xrealloc (code, strlen (code)
- + strlen ("captures[") + 4);
- if (token->flags & PREV_WHITE)
- strcat (code, " ");
- strcat (code, "captures[");
- strcat (code, get_number (r));
- strcat (code, "]");
- continue;
- }
- }
-
/* Count brace pairs to find the end of the expr to match. */
if (token->type == start)
opencnt++;
@@ -760,27 +852,14 @@ parse_c_expr (cpp_reader *r, cpp_ttype s
&& --opencnt == 0)
break;
- /* Output the token as string. */
- char *tk = (char *)cpp_token_as_text (r, token);
- code = (char *)xrealloc (code, strlen (code) + strlen (tk) + 2);
- if (token->flags & PREV_WHITE)
- strcat (code, " ");
- strcat (code, tk);
+ if (token->type == CPP_SEMICOLON)
+ nr_stmts++;
+
+ /* Record the token. */
+ code.safe_push (*token);
}
while (1);
- if (end == CPP_CLOSE_PAREN)
- {
- code = (char *)xrealloc (code, strlen (code) + 1 + 1);
- strcat (code, ")");
- }
- else if (end == CPP_CLOSE_BRACE)
- {
- code = (char *)xrealloc (code, strlen (code) + 1 + 2);
- strcat (code, "})");
- }
- else
- gcc_unreachable ();
- return new c_expr (code);
+ return new c_expr (r, code, nr_stmts);
}
/* Parse
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-06-03 13:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-03 13:15 [PATCH][match-and-simplify] Get rid of some stmt expressions Richard Biener
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).