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  <rguent...@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.

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)

Reply via email to