public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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).