diff mbox

[match-and-simplify] GENERIC code-gen

Message ID alpine.LSU.2.11.1406241711160.29270@zhemvz.fhfr.qr
State New
Headers show

Commit Message

Richard Biener June 24, 2014, 3:30 p.m. UTC
This massages things so GENERIC code-gen works (well, is emitted
and compiles).  The GENERIC interface matches that of 
fold_{unary,binary,ternary} with also supporting calls here.
It's supposed to be called at the start of those functions
(and if it returns NULL_TREE their remains is executed).

At the moment it just creates dead code.  I'll see if it works
to wire it in tomorrow.

Committed.

Richard.

2014-06-24  Richard Biener  <rguenther@suse.de>

	* genmatch.c (operand::gen_gimple_transform): Rename to...
	(operand::gen_transform): ... this and add a flag argument for
	the kind of IL to generate.
	(predicate::gen_gimple_transform): Likewise.
	(expr::gen_gimple_transform): Likewise.
	(c_expr::gen_gimple_transform): Likewise.
	(capture::gen_gimple_transform): Likewise.
	(dt_node::gen_generic): Add.
	(dt_operand::gen_generic_expr): Add flag whether to valueize.
	(dt_operand::gen_generic_expr_expr): Likewise.
	(dt_operand::gen_generic_expr_fn): Likewise.
	(dt_simplify::gen_genric): Add.
	(decision_tree::gen_generic): Likewise.
	(main): Uncomment generic codegen.
diff mbox

Patch

Index: genmatch.c
===================================================================
--- genmatch.c	(revision 211941)
+++ genmatch.c	(working copy)
@@ -206,14 +206,14 @@  struct operand {
   enum op_type { OP_PREDICATE, OP_EXPR, OP_CAPTURE, OP_C_EXPR };
   operand (enum op_type type_) : type (type_) {}
   enum op_type type;
-  virtual void gen_gimple_transform (FILE *f, const char *) = 0;
+  virtual void gen_transform (FILE *f, const char *, bool) = 0;
 };
 
 struct predicate : public operand
 {
   predicate (const char *ident_) : operand (OP_PREDICATE), ident (ident_) {}
   const char *ident;
-  virtual void gen_gimple_transform (FILE *, const char *) { gcc_unreachable (); }
+  virtual void gen_transform (FILE *, const char *, bool) { gcc_unreachable (); }
 };
 
 struct e_operation {
@@ -230,7 +230,7 @@  struct expr : public operand
   void append_op (operand *op) { ops.safe_push (op); }
   e_operation *operation;
   vec<operand *> ops;
-  virtual void gen_gimple_transform (FILE *f, const char *);
+  virtual void gen_transform (FILE *f, const char *, bool);
 };
 
 struct c_expr : public operand
@@ -242,7 +242,7 @@  struct c_expr : public operand
   vec<cpp_token> code;
   unsigned nr_stmts;
   char *fname;
-  virtual void gen_gimple_transform (FILE *f, const char *);
+  virtual void gen_transform (FILE *f, const char *, bool);
 };
 
 struct capture : public operand
@@ -251,7 +251,7 @@  struct capture : public operand
       : operand (OP_CAPTURE), where (where_), what (what_) {}
   const char *where;
   operand *what;
-  virtual void gen_gimple_transform (FILE *f, const char *);
+  virtual void gen_transform (FILE *f, const char *, bool);
 };
 
 
@@ -324,6 +324,7 @@  struct dt_node
   dt_node *append_simplify (simplify *, unsigned, dt_operand **); 
 
   virtual void gen_gimple (FILE *) {}
+  virtual void gen_generic (FILE *) {}
 };
 
 struct dt_operand: public dt_node
@@ -337,6 +338,7 @@  struct dt_operand: public dt_node
 	: dt_node (type), op (op_), match_dop (match_dop_), parent (parent_), pos (pos_) {} 
 
   virtual void gen_gimple (FILE *);
+  virtual void gen_generic (FILE *);
   unsigned gen_gimple_predicate (FILE *, const char *);
   unsigned gen_gimple_match_op (FILE *, const char *);
 
@@ -344,9 +346,9 @@  struct dt_operand: public dt_node
   void gen_gimple_expr_expr (FILE *, expr *);
   void gen_gimple_expr_fn (FILE *, expr *);
 
-  unsigned gen_generic_expr (FILE *, const char *);
-  void gen_generic_expr_expr (FILE *, expr *, const char *);
-  void gen_generic_expr_fn (FILE *, expr *, const char *);
+  unsigned gen_generic_expr (FILE *, const char *, bool);
+  void gen_generic_expr_expr (FILE *, expr *, const char *, bool);
+  void gen_generic_expr_fn (FILE *, expr *, const char *, bool);
 
   char *get_name (char *);
   void gen_opname (char *, unsigned);
@@ -369,6 +371,7 @@  struct dt_simplify: public dt_node
   }
 
   virtual void gen_gimple (FILE *f);
+  virtual void gen_generic (FILE *f);
 };
 
 struct decision_tree
@@ -377,6 +380,7 @@  struct decision_tree
   
   void insert (struct simplify *, unsigned); 
   void gen_gimple (FILE *f = stderr);
+  void gen_generic (FILE *f = stderr);
   void print (FILE *f = stderr);
 
   decision_tree () { root = new dt_node (dt_node::DT_NODE); }
@@ -535,7 +539,7 @@  commutate (operand *op)
 /* Code gen off the AST.  */
 
 void
-expr::gen_gimple_transform (FILE *f, const char *dest)
+expr::gen_transform (FILE *f, const char *dest, bool gimple)
 {
   fprintf (f, "{\n");
   fprintf (f, "  tree ops[%u], res;\n", ops.length ());
@@ -543,31 +547,46 @@  expr::gen_gimple_transform (FILE *f, con
     {
       char dest[32];
       snprintf (dest, 32, "  ops[%u]", i);
-      ops[i]->gen_gimple_transform (f, dest);
+      ops[i]->gen_transform (f, dest, gimple);
+    }
+  if (gimple)
+    {
+      /* ???  Have another helper that is like gimple_build but may
+	 fail if seq == NULL.  */
+      fprintf (f, "  if (!seq)\n"
+	       "    {\n"
+	       "      res = gimple_match_and_simplify (%s, TREE_TYPE (ops[0])",
+	       operation->op->id);
+      for (unsigned i = 0; i < ops.length (); ++i)
+	fprintf (f, ", ops[%u]", i);
+      fprintf (f, ", seq, valueize);\n");
+      fprintf (f, "      if (!res) return false;\n");
+      fprintf (f, "    }\n");
+      fprintf (f, "  else\n");
+      fprintf (f, "    res = gimple_build (seq, UNKNOWN_LOCATION, %s, "
+	       "TREE_TYPE (ops[0])", operation->op->id);
+      for (unsigned i = 0; i < ops.length (); ++i)
+	fprintf (f, ", ops[%u]", i);
+      fprintf (f, ", valueize);\n");
+    }
+  else
+    {
+      if (operation->op->kind == id_base::CODE)
+	fprintf (f, "  res = fold_build%d (%s, TREE_TYPE (ops[0])",
+		 ops.length(), operation->op->id);
+      else
+	fprintf (f, "  res = build_call_expr (builtin_decl_implicit (%s), %d",
+		 operation->op->id, ops.length());
+      for (unsigned i = 0; i < ops.length (); ++i)
+	fprintf (f, ", ops[%u]", i);
+      fprintf (f, ");\n");
     }
-  /* ???  Have another helper that is like gimple_build but may
-     fail if seq == NULL.  */
-  fprintf (f, "  if (!seq)\n"
-	   "    {\n"
-	   "      res = gimple_match_and_simplify (%s, TREE_TYPE (ops[0])",
-	   operation->op->id);
-  for (unsigned i = 0; i < ops.length (); ++i)
-    fprintf (f, ", ops[%u]", i);
-  fprintf (f, ", seq, valueize);\n");
-  fprintf (f, "      if (!res) return false;\n");
-  fprintf (f, "    }\n");
-  fprintf (f, "  else\n");
-  fprintf (f, "    res = gimple_build (seq, UNKNOWN_LOCATION, %s, "
-	   "TREE_TYPE (ops[0])", operation->op->id);
-  for (unsigned i = 0; i < ops.length (); ++i)
-    fprintf (f, ", ops[%u]", i);
-  fprintf (f, ", valueize);\n");
   fprintf (f, "  %s = res;\n", dest);
   fprintf (f, "}");
 }
 
 void
-c_expr::gen_gimple_transform (FILE *f, const char *dest)
+c_expr::gen_transform (FILE *f, const char *dest, bool gimple)
 {
   /* If this expression has an outlined function variant, call it.  */
   if (fname)
@@ -614,7 +633,7 @@  c_expr::gen_gimple_transform (FILE *f, c
 }
 
 void
-capture::gen_gimple_transform (FILE *f, const char *dest)
+capture::gen_transform (FILE *f, const char *dest, bool)
 {
   fprintf (f, "%s = captures[%s];\n", dest, where); 
 }
@@ -949,7 +968,8 @@  dt_operand::gen_gimple_expr (FILE *f, co
 
 
 void
-dt_operand::gen_generic_expr_expr (FILE *f, expr *e, const char *opname)
+dt_operand::gen_generic_expr_expr (FILE *f, expr *e, const char *opname,
+				   bool valueize)
 {
   unsigned n_ops = e->ops.length ();
 
@@ -962,13 +982,16 @@  dt_operand::gen_generic_expr_expr (FILE
       gen_opname (child_opname, i);
 
       fprintf (f, "tree %s = TREE_OPERAND (%s, %u);\n", child_opname, opname, i);
-      fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
-      fprintf (f, "{\n");
+      if (valueize)
+	{
+	  fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
+	  fprintf (f, "{\n");
+	}
     }
 }   
 
 void
-dt_operand::gen_generic_expr_fn (FILE *f, expr *e, const char *opname)
+dt_operand::gen_generic_expr_fn (FILE *f, expr *e, const char *opname, bool valueize)
 {
   unsigned n_ops = e->ops.length ();
   fn_id *op = static_cast <fn_id *> (e->operation->op);
@@ -987,17 +1010,20 @@  dt_operand::gen_generic_expr_fn (FILE *f
       gen_opname (child_opname, i);
 
       fprintf (f, "tree %s = CALL_EXPR_ARG (%s, %u);\n", child_opname, opname, i);
-      fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
-      fprintf (f, "{\n");
+      if (valueize)
+	{
+	  fprintf (f, "if ((%s = do_valueize (valueize, %s)) != 0)\n", child_opname, child_opname);
+	  fprintf (f, "{\n");
+	}
     }
 }
 
 unsigned
-dt_operand::gen_generic_expr (FILE *f, const char *opname)
+dt_operand::gen_generic_expr (FILE *f, const char *opname, bool valueize)
 {
   expr *e = static_cast<expr *> (op);
-  (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e, opname) : gen_generic_expr_fn (f, e, opname);
-  return e->ops.length () + 1;
+  (e->operation->op->kind == id_base::CODE) ? gen_generic_expr_expr (f, e, opname, valueize) : gen_generic_expr_fn (f, e, opname, valueize);
+  return valueize ? e->ops.length () + 1 : 1;
 }
 
 void
@@ -1024,14 +1050,14 @@  dt_operand::gen_gimple (FILE *f)
 	  enum tree_code code = op_id->code;
 
 	  if (code == REALPART_EXPR || code == IMAGPART_EXPR || code == VIEW_CONVERT_EXPR || code == BIT_FIELD_REF)
-	    n_braces = gen_generic_expr (f, opname);
+	    n_braces = gen_generic_expr (f, opname, true);
 
 	  // check for cond_expr, 0th operand -> generic
 	  else if (parent->type == dt_node::DT_OPERAND && parent->op->type == operand::OP_EXPR)
 	    {
 	      e = static_cast<expr *> (parent->op);
 	      op_id = static_cast <operator_id *> (e->operation->op);
-	      n_braces = (op_id->code == COND_EXPR && pos == 0) ? gen_generic_expr (f, opname) : gen_gimple_expr (f, opname);
+	      n_braces = (op_id->code == COND_EXPR && pos == 0) ? gen_generic_expr (f, opname, true) : gen_gimple_expr (f, opname);
 	    }
 	  else
 	    n_braces = gen_gimple_expr (f, opname);
@@ -1060,6 +1086,48 @@  dt_operand::gen_gimple (FILE *f)
 }
 
 void
+dt_operand::gen_generic (FILE *f)
+{
+  char opname[20];
+  get_name (opname); 
+
+  fprintf (f, "{\n");
+
+  unsigned n_braces = 0;
+ 
+  if (type == DT_OPERAND)
+    switch (op->type)
+      {
+	case operand::OP_PREDICATE:
+	  n_braces = gen_gimple_predicate (f, opname);
+	  break;
+
+	case operand::OP_EXPR:
+	  n_braces = gen_generic_expr (f, opname, false);
+	  break;
+
+	default:
+	  gcc_unreachable ();
+      }
+  else if (type == DT_TRUE)
+    ;
+  else if (type == DT_MATCH)
+    n_braces = gen_gimple_match_op (f, opname);
+  else
+    gcc_unreachable ();
+
+  unsigned i;
+
+  for (i = 0; i < kids.length (); ++i)
+    kids[i]->gen_generic (f);
+
+  for (i = 0; i < n_braces; ++i)
+    fprintf (f, "}\n");
+  
+  fprintf (f, "}\n");
+}
+
+void
 dt_simplify::gen_gimple (FILE *f)
 {
 
@@ -1079,7 +1147,7 @@  dt_simplify::gen_gimple (FILE *f)
 	{
 	  output_line_directive (f, s->ifexpr_location);
 	  fprintf (f, "if (");
-	  s->ifexpr->gen_gimple_transform (f, NULL);
+	  s->ifexpr->gen_transform (f, NULL, true);
 	  fprintf (f, ")\n");
 	  fprintf (f, "{\n");
 	}
@@ -1093,7 +1161,7 @@  dt_simplify::gen_gimple (FILE *f)
 	    {
 	      char dest[32];
 	      snprintf (dest, 32, "  res_ops[%d]", j);
-	      e->ops[j]->gen_gimple_transform (f, dest);
+	      e->ops[j]->gen_transform (f, dest, true);
 	    }
 	  /* Re-fold the toplevel result.  It's basically an embedded
 	     gimple_build w/o actually building the stmt.  */
@@ -1103,8 +1171,7 @@  dt_simplify::gen_gimple (FILE *f)
       else if (s->result->type == operand::OP_CAPTURE
 	       || s->result->type == operand::OP_C_EXPR)
 	{
-	  s->result->gen_gimple_transform (f,
-					   "res_ops[0]");
+	  s->result->gen_transform (f, "res_ops[0]", true);
 	  fprintf (f, "*res_code = TREE_CODE (res_ops[0]);\n");
 	}
       else
@@ -1118,6 +1185,70 @@  dt_simplify::gen_gimple (FILE *f)
 }
 
 
+void
+dt_simplify::gen_generic (FILE *f)
+{
+
+  fprintf (f, "/* simplify %u */\n", pattern_no);
+
+  fprintf (f, "{\n");
+  fprintf (f, "tree captures[4] = {};\n");
+
+  for (unsigned i = 0; i < dt_simplify::capture_max; ++i)
+    if (indexes[i])
+      {
+	char opname[20];
+	fprintf (f, "captures[%u] = %s;\n", i, indexes[i]->get_name (opname));
+      }
+
+  if (s->ifexpr)
+	{
+	  output_line_directive (f, s->ifexpr_location);
+	  fprintf (f, "if (");
+	  s->ifexpr->gen_transform (f, NULL, false);
+	  fprintf (f, ")\n");
+	  fprintf (f, "{\n");
+	}
+      output_line_directive (f, s->result_location);
+
+      if (s->result->type == operand::OP_EXPR)
+	{
+	  expr *e = static_cast <expr *> (s->result);
+	  for (unsigned j = 0; j < e->ops.length (); ++j)
+	    {
+	      fprintf (f, "   tree res_op%d;\n", j);
+	      char dest[32];
+	      snprintf (dest, 32, "  res_op%d", j);
+	      e->ops[j]->gen_transform (f, dest, false);
+	    }
+	  /* Re-fold the toplevel result.  */
+	  if (e->operation->op->kind == id_base::CODE)
+	    fprintf (f, "  return fold_build%d (%s, TREE_TYPE (res_op0)",
+		     e->ops.length (), e->operation->op->id);
+	  else
+	    fprintf (f, "  return build_call_expr (builtin_decl_implicit (%s), %d",
+		     e->operation->op->id, e->ops.length());
+	  for (unsigned j = 0; j < e->ops.length (); ++j)
+	    fprintf (f, ", res_op%d", j);
+	  fprintf (f, ");\n");
+	}
+      else if (s->result->type == operand::OP_CAPTURE
+	       || s->result->type == operand::OP_C_EXPR)
+	{
+	  fprintf (f, "  tree res;\n");
+	  s->result->gen_transform (f, " res", false);
+	  fprintf (f, "  return res;\n");
+	}
+      else
+	gcc_unreachable ();
+
+      if (s->ifexpr)
+	fprintf (f, "}\n");
+
+  fprintf (f, "}\n");
+}
+
+
 
 void
 decision_tree::gen_gimple (FILE *f)
@@ -1152,6 +1283,37 @@  decision_tree::gen_gimple (FILE *f)
 }
 
 
+void
+decision_tree::gen_generic (FILE *f)
+{
+  fprintf (f, "tree\n"
+	   "generic_match_and_simplify (code_helper code, tree type");
+  for (unsigned i = 0; i < 3; ++i)
+    fprintf (f, ", tree op%d", i);
+  fprintf (f, ")\n");
+  fprintf (f, "{\n");
+
+  for (unsigned i = 0; i < root->kids.length (); i++)
+    {
+      dt_operand *dop = static_cast<dt_operand *>(root->kids[i]);
+      expr *e = static_cast<expr *>(dop->op);
+
+      if (i)
+        fprintf (f, "else ");
+      fprintf (f, "if (code == %s)\n", e->operation->op->id);
+      fprintf (f, "{\n");
+
+      for (unsigned j = 0; j < dop->kids.length (); ++j)
+	dop->kids[j]->gen_generic (f);
+
+      fprintf (f, "}\n");
+    }
+
+  fprintf (f, "return NULL_TREE;\n");
+  fprintf (f, "}\n");
+}
+
+
 static void
 outline_c_exprs (FILE *f, struct operand *op)
 {
@@ -1602,7 +1764,7 @@  main(int argc, char **argv)
   else if (strcmp (argv[1], "-generic") == 0)
     {
       write_header (stdout, simplifiers, "generic-match-head.c");
-      //dt.gen_generic (stdout);
+      dt.gen_generic (stdout);
     }
   else
     return 1;