diff mbox

[match-and-simplify] Auto-guess conversion types

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

Commit Message

Richard Biener Aug. 21, 2014, 11:23 a.m. UTC
This adds the capability to auto-guess the type of non-outermost
conversions by looking at the parent expression type.  This also
adds fatal () to the cases we can't auto-detect.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

Richard.

2014-08-21  Richard Biener  <rguenther@suse.de>

	* genmatch.c (*::gen_transform): Add type parameter.
	(expr::gen_transform): Handle conversion operators by
	converting to the parent expression type.  Properly
	pass down the expression type to children.
	(dt_simplify::gen_gimple): Pass down 'type' to gen_transform.
	(dt_simplify::gen_generic): Likewise.
	* match.pd ((T1)(~(T2) X)  -> ~(T1) X): New pattern.

Comments

Marc Glisse Aug. 21, 2014, 12:36 p.m. UTC | #1
On Thu, 21 Aug 2014, Richard Biener wrote:

> +/* From fold_unary.  */
> +
> +/* (T1)(~(T2) X)  -> ~(T1) X */
> +(simplify
> + (convert (bit_not@0 (convert @1)))
> + (if (INTEGRAL_TYPE_P (type)
> +      && INTEGRAL_TYPE_P (TREE_TYPE (@0))
> +      && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0))
> +      && INTEGRAL_TYPE_P (TREE_TYPE (@1))
> +      && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)))
> +  (bit_not (convert (bit_not @0)))))

There are a lot of bit_not in this line...

I know the patterns themselves aren't your main preoccupation right now, 
and I agree that finishing the infrastructure is the priority, but it 
seems that the comments are becoming much terser during the move from 
fold-const to *.pd. I believe the == could be <=, so I wanted to check the 
rationale, and fold-const at least tries to explain the condition. It 
would be nice to copy-paste those comments, if the version in fold-const.c 
is supposed to disappear.

(if that's planned for later, please ignore my message)
diff mbox

Patch

Index: gcc/match.pd
===================================================================
--- gcc/match.pd	(revision 214224)
+++ gcc/match.pd	(working copy)
@@ -107,6 +107,19 @@  along with GCC; see the file COPYING3.
   (abs @0))
 
 
+/* From fold_unary.  */
+
+/* (T1)(~(T2) X)  -> ~(T1) X */
+(simplify
+ (convert (bit_not@0 (convert @1)))
+ (if (INTEGRAL_TYPE_P (type)
+      && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+      && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (@0))
+      && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+      && TYPE_PRECISION (type) <= TYPE_PRECISION (TREE_TYPE (@1)))
+  (bit_not (convert (bit_not @0)))))
+
+
 #include "match-plusminus.pd"
 #include "match-bitwise.pd"
 #include "match-rotate.pd"
Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 214258)
+++ gcc/genmatch.c	(working copy)
@@ -238,14 +238,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_transform (FILE *f, const char *, bool, int) = 0;
+  virtual void gen_transform (FILE *f, const char *, bool, int, const char *) = 0;
 };
 
 struct predicate : public operand
 {
   predicate (const char *ident_) : operand (OP_PREDICATE), ident (ident_) {}
   const char *ident;
-  virtual void gen_transform (FILE *, const char *, bool, int)
+  virtual void gen_transform (FILE *, const char *, bool, int, const char *)
     { gcc_unreachable (); }
 };
 
@@ -263,7 +263,7 @@  struct expr : public operand
   void append_op (operand *op) { ops.safe_push (op); }
   e_operation *operation;
   vec<operand *> ops;
-  virtual void gen_transform (FILE *f, const char *, bool, int);
+  virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
 };
 
 struct c_expr : public operand
@@ -286,7 +286,7 @@  struct c_expr : public operand
   char *fname;
   vec<id_tab> ids;
 
-  virtual void gen_transform (FILE *f, const char *, bool, int);
+  virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
   void output_code (FILE *f, bool);
 };
 
@@ -296,7 +296,7 @@  struct capture : public operand
       : operand (OP_CAPTURE), where (where_), what (what_) {}
   const char *where;
   operand *what;
-  virtual void gen_transform (FILE *f, const char *, bool, int);
+  virtual void gen_transform (FILE *f, const char *, bool, int, const char *);
 };
 
 template<>
@@ -860,32 +860,71 @@  check_no_user_id (simplify *s)
 /* Code gen off the AST.  */
 
 void
-expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth)
+expr::gen_transform (FILE *f, const char *dest, bool gimple, int depth,
+		     const char *in_type)
 {
+  bool is_conversion = false;
+  if (*operation->op == CONVERT_EXPR
+      || *operation->op == NOP_EXPR
+      || *operation->op == FLOAT_EXPR
+      || *operation->op == FIX_TRUNC_EXPR)
+    is_conversion = true;
+
+  const char *type;
+  char optype[20];
+  if (is_conversion)
+    /* For conversions we need to build the expression using the
+       outer type passed in.  */
+    type = in_type;
+  else
+    {
+      /* Other operations are of the same type as their first operand.  */
+      sprintf (optype, "TREE_TYPE (ops%d[0])", depth);
+      type = optype;
+    }
+  if (!type)
+    fatal ("two conversions in a row");
+
   fprintf (f, "{\n");
   fprintf (f, "  tree ops%d[%u], res;\n", depth, ops.length ());
   for (unsigned i = 0; i < ops.length (); ++i)
     {
       char dest[32];
       snprintf (dest, 32, "  ops%d[%u]", depth, i);
-      ops[i]->gen_transform (f, dest, gimple, depth + 1);
+      ops[i]->gen_transform (f, dest, gimple, depth + 1,
+			     is_conversion
+			     /* If this op is a conversion its single
+			        operand has to know its type itself.  */
+			     ? NULL
+			     /* For other ops the type is the type
+			        we got passed in, or if that is from
+				a conversion we can at most use the
+				first operand type for all further
+				operands.  So (convert (plus @1 (convert @2))
+				is possible while
+				(convert (plus (convert @1) @2))
+				is not unless we somehow discover what
+				operand we can generate first and do it
+				in the appropriate order.  */
+			     : (i == 0 ? in_type : type));
     }
+
   if (gimple)
     {
       /* ???  Have another helper that is like gimple_build but may
 	 fail if seq == NULL.  */
       fprintf (f, "  if (!seq)\n"
 	       "    {\n"
-	       "      res = gimple_simplify (%s, TREE_TYPE (ops%d[0])",
-	       operation->op->id, depth);
+	       "      res = gimple_simplify (%s, %s",
+	       operation->op->id, type);
       for (unsigned i = 0; i < ops.length (); ++i)
 	fprintf (f, ", ops%d[%u]", depth, 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%d[0])", operation->op->id, depth);
+      fprintf (f, "    res = gimple_build (seq, UNKNOWN_LOCATION, %s, %s",
+	       operation->op->id, type);
       for (unsigned i = 0; i < ops.length (); ++i)
 	fprintf (f, ", ops%d[%u]", depth, i);
       fprintf (f, ", valueize);\n");
@@ -893,8 +932,8 @@  expr::gen_transform (FILE *f, const char
   else
     {
       if (operation->op->kind == id_base::CODE)
-	fprintf (f, "  res = fold_build%d (%s, TREE_TYPE (ops%d[0])",
-		 ops.length(), operation->op->id, depth);
+	fprintf (f, "  res = fold_build%d (%s, %s",
+		 ops.length(), operation->op->id, type);
       else
 	fprintf (f, "  res = build_call_expr (builtin_decl_implicit (%s), %d",
 		 operation->op->id, ops.length());
@@ -965,7 +1004,7 @@  c_expr::output_code (FILE *f, bool for_f
 
 
 void
-c_expr::gen_transform (FILE *f, const char *dest, bool, int)
+c_expr::gen_transform (FILE *f, const char *dest, bool, int, const char *)
 {
   /* If this expression has an outlined function variant, call it.  */
   if (fname)
@@ -985,7 +1024,7 @@  c_expr::gen_transform (FILE *f, const ch
 }
 
 void
-capture::gen_transform (FILE *f, const char *dest, bool, int)
+capture::gen_transform (FILE *f, const char *dest, bool, int, const char *)
 {
   fprintf (f, "%s = captures[%s];\n", dest, where); 
 }
@@ -1673,7 +1712,7 @@  dt_simplify::gen_gimple (FILE *f)
       for (unsigned i = s->ifexpr_vec.length (); i; --i)
 	{
 	  fprintf (f, "(");
-	  s->ifexpr_vec[i - 1]->gen_transform (f, NULL, true, 1);
+	  s->ifexpr_vec[i - 1]->gen_transform (f, NULL, true, 1, "type");
 	  fprintf (f, ")");
 	  if (i > 1)
 	    fprintf (f, " && ");
@@ -1691,7 +1730,7 @@  dt_simplify::gen_gimple (FILE *f)
 	    {
 	      char dest[32];
 	      snprintf (dest, 32, "  res_ops[%d]", j);
-	      e->ops[j]->gen_transform (f, dest, true, 1);
+	      e->ops[j]->gen_transform (f, dest, true, 1, "type");
 	    }
 	  /* Re-fold the toplevel result.  It's basically an embedded
 	     gimple_build w/o actually building the stmt.  */
@@ -1701,7 +1740,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_transform (f, "res_ops[0]", true, 1);
+	  s->result->gen_transform (f, "res_ops[0]", true, 1, "type");
 	  fprintf (f, "*res_code = TREE_CODE (res_ops[0]);\n");
 	}
       else
@@ -1738,7 +1777,7 @@  dt_simplify::gen_generic (FILE *f)
       for (unsigned i = s->ifexpr_vec.length (); i; --i)
         {
           fprintf (f, "(");
-          s->ifexpr_vec[i - 1]->gen_transform (f, NULL, false, 1);
+          s->ifexpr_vec[i - 1]->gen_transform (f, NULL, false, 1, "type");
           fprintf (f, ")");
           if (i > 1)
             fprintf (f, " && ");
@@ -1757,7 +1796,7 @@  dt_simplify::gen_generic (FILE *f)
 	      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, 1);
+	      e->ops[j]->gen_transform (f, dest, false, 1, "type");
 	    }
 	  /* Re-fold the toplevel result.  */
 	  if (e->operation->op->kind == id_base::CODE)
@@ -1774,7 +1813,7 @@  dt_simplify::gen_generic (FILE *f)
 	       || s->result->type == operand::OP_C_EXPR)
 	{
 	  fprintf (f, "  tree res;\n");
-	  s->result->gen_transform (f, " res", false, 1);
+	  s->result->gen_transform (f, " res", false, 1, "type");
 	  fprintf (f, "  return res;\n");
 	}
       else