Patchwork [match-and-simplify] Fix type guessing for conversions

login
register
mail settings
Submitter Richard Guenther
Date Aug. 27, 2014, 12:04 p.m.
Message ID <alpine.LSU.2.11.1408271401010.20733@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/383436/
State New
Headers show

Comments

Richard Guenther - Aug. 27, 2014, 12:04 p.m.
The following fixes type guessing by handling VIEW_CONVERT_EXPR
and by properly passing down "unknown" for outermost conversions.

Btw, a case where we need some explicit type specification support
is Convert (T1)(X * Y) into (T1)X * (T1)Y which needs to eventually
use an unsigned type for the multiplication.  Suggested syntax
could be

/* Convert (T1)(X * Y) into (T1)X * (T1)Y if T1 is narrower than the
   type of X and Y (integer types only).  */
(simplify
 (convert (mult @0 @1))
 (if (INTEGRAL_TYPE_P (type)
      && INTEGRAL_TYPE_P (TREE_TYPE (@0))
      && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (@0)))
  (if (TYPE_OVERFLOW_WRAPS (type))
   (mult (convert @0) (convert @1)))
  /* 1) We can't handle the two-conversions-in-a-row below.
     2) We can't properly specify the type for the inner conversion
        (unsigned_type_for).  Suggested syntax below.  */
  (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
   (convert (mult (convert:utype @0) (convert:utype @1))))))

Committed.

Richard.

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

	* genmatch.c (is_conversion): New helper, add VIEW_CONVERT_EXPR
	to the list of conversions.
	(expr::gen_transform): Use it.
	(dt_simplify::gen): Properly pass down NULL as the operand
	type for outermost conversions.

Patch

Index: gcc/genmatch.c
===================================================================
--- gcc/genmatch.c	(revision 214568)
+++ gcc/genmatch.c	(working copy)
@@ -866,22 +866,27 @@  check_no_user_id (simplify *s)
   check_no_user_id (s->result);
 }
 
+bool
+is_conversion (id_base *op)
+{
+  return (*op == CONVERT_EXPR
+	  || *op == NOP_EXPR
+	  || *op == FLOAT_EXPR
+	  || *op == FIX_TRUNC_EXPR
+	  || *op == VIEW_CONVERT_EXPR);
+}
+
 /* Code gen off the AST.  */
 
 void
 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;
+  bool conversion_p = is_conversion (operation->op);
 
   const char *type;
   char optype[20];
-  if (is_conversion)
+  if (conversion_p)
     /* For conversions we need to build the expression using the
        outer type passed in.  */
     type = in_type;
@@ -901,7 +906,7 @@  expr::gen_transform (FILE *f, const char
       char dest[32];
       snprintf (dest, 32, "  ops%d[%u]", depth, i);
       ops[i]->gen_transform (f, dest, gimple, depth + 1,
-			     is_conversion
+			     conversion_p
 			     /* If this op is a conversion its single
 			        operand has to know its type itself.  */
 			     ? NULL
@@ -1769,7 +1774,9 @@  dt_simplify::gen (FILE *f, bool gimple)
 	    {
 	      char dest[32];
 	      snprintf (dest, 32, "  res_ops[%d]", j);
-	      e->ops[j]->gen_transform (f, dest, true, 1, "type");
+	      e->ops[j]->gen_transform (f, dest, true, 1,
+					is_conversion (e->operation->op)
+					? NULL : "type");
 	    }
 	  /* Re-fold the toplevel result.  It's basically an embedded
 	     gimple_build w/o actually building the stmt.  */
@@ -1796,7 +1803,9 @@  dt_simplify::gen (FILE *f, bool gimple)
 	      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, "type");
+	      e->ops[j]->gen_transform (f, dest, false, 1,
+					is_conversion (e->operation->op)
+					? NULL : "type");
 	    }
 	  /* Re-fold the toplevel result.  */
 	  if (e->operation->op->kind == id_base::CODE)