Patchwork Fix up vector CONSTRUCTOR handling (PR tree-optimization/54713)

login
register
mail settings
Submitter Jakub Jelinek
Date Sept. 28, 2012, 11:31 a.m.
Message ID <20120928113126.GC1787@tucnak.redhat.com>
Download mbox | patch
Permalink /patch/187772/
State New
Headers show

Comments

Jakub Jelinek - Sept. 28, 2012, 11:31 a.m.
Hi!

As discussed in the PR, tree-vect-generic.c sometimes creates CONSTRUCTORs
with vector elements to build up larger vectors from vectors supported by
HW.  This patch teaches fold-const to bail up on those.  Vector CONSTRUCTOR
verification changes and assorted fixes have been separated from the patch
and will be posted probably next week.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2012-09-28  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/54713
	* fold-const.c (vec_cst_ctor_to_array): Give up if vector CONSTRUCTOR
	has vector elements.
	(fold_ternary_loc) <case BIT_FIELD_REF>: Likewise.
	* tree-vect-generic.c (vector_element): Don't rely on CONSTRUCTOR elts
	indexes.  Use BIT_FIELD_REF if CONSTRUCTOR has vector elements.
	(lower_vec_perm): Use NULL_TREE CONSTRUCTOR indexes.

	* gcc.c-torture/compile/pr54713-1.c: New test.
	* gcc.c-torture/compile/pr54713-2.c: New test.
	* gcc.c-torture/compile/pr54713-3.c: New test.


	Jakub
Richard Guenther - Sept. 28, 2012, 11:45 a.m.
On Fri, Sep 28, 2012 at 1:31 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> As discussed in the PR, tree-vect-generic.c sometimes creates CONSTRUCTORs
> with vector elements to build up larger vectors from vectors supported by
> HW.  This patch teaches fold-const to bail up on those.  Vector CONSTRUCTOR
> verification changes and assorted fixes have been separated from the patch
> and will be posted probably next week.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

> 2012-09-28  Jakub Jelinek  <jakub@redhat.com>
>
>         PR tree-optimization/54713
>         * fold-const.c (vec_cst_ctor_to_array): Give up if vector CONSTRUCTOR
>         has vector elements.
>         (fold_ternary_loc) <case BIT_FIELD_REF>: Likewise.
>         * tree-vect-generic.c (vector_element): Don't rely on CONSTRUCTOR elts
>         indexes.  Use BIT_FIELD_REF if CONSTRUCTOR has vector elements.
>         (lower_vec_perm): Use NULL_TREE CONSTRUCTOR indexes.
>
>         * gcc.c-torture/compile/pr54713-1.c: New test.
>         * gcc.c-torture/compile/pr54713-2.c: New test.
>         * gcc.c-torture/compile/pr54713-3.c: New test.
>
> --- gcc/fold-const.c.jj 2012-09-25 11:59:43.000000000 +0200
> +++ gcc/fold-const.c    2012-09-26 13:14:05.639000395 +0200
> @@ -9559,7 +9559,7 @@ vec_cst_ctor_to_array (tree arg, tree *e
>        constructor_elt *elt;
>
>        FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (arg), i, elt)
> -       if (i >= nelts)
> +       if (i >= nelts || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
>           return false;
>         else
>           elts[i] = elt->value;
> @@ -14030,22 +14030,35 @@ fold_ternary_loc (location_t loc, enum t
>                       unsigned i;
>                       if (CONSTRUCTOR_NELTS (arg0) == 0)
>                         return build_constructor (type, NULL);
> -                     vals = VEC_alloc (constructor_elt, gc, n);
> -                     for (i = 0; i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
> -                          ++i)
> -                       CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
> -                                               CONSTRUCTOR_ELT
> -                                                 (arg0, idx + i)->value);
> -                     return build_constructor (type, vals);
> +                     if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
> +                                                                0)->value))
> +                         != VECTOR_TYPE)
> +                       {
> +                         vals = VEC_alloc (constructor_elt, gc, n);
> +                         for (i = 0;
> +                              i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
> +                              ++i)
> +                           CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
> +                                                   CONSTRUCTOR_ELT
> +                                                     (arg0, idx + i)->value);
> +                         return build_constructor (type, vals);
> +                       }
>                     }
>                 }
>               else if (n == 1)
>                 {
>                   if (TREE_CODE (arg0) == VECTOR_CST)
>                     return VECTOR_CST_ELT (arg0, idx);
> -                 else if (idx < CONSTRUCTOR_NELTS (arg0))
> -                   return CONSTRUCTOR_ELT (arg0, idx)->value;
> -                 return build_zero_cst (type);
> +                 else if (CONSTRUCTOR_NELTS (arg0) == 0)
> +                   return build_zero_cst (type);
> +                 else if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
> +                                                                 0)->value))
> +                          != VECTOR_TYPE)
> +                   {
> +                     if (idx < CONSTRUCTOR_NELTS (arg0))
> +                       return CONSTRUCTOR_ELT (arg0, idx)->value;
> +                     return build_zero_cst (type);
> +                   }
>                 }
>             }
>         }
> --- gcc/tree-vect-generic.c.jj  2012-09-18 12:14:48.000000000 +0200
> +++ gcc/tree-vect-generic.c     2012-09-26 14:23:40.742171292 +0200
> @@ -1050,14 +1050,13 @@ vector_element (gimple_stmt_iterator *gs
>
>        if (TREE_CODE (vect) == VECTOR_CST)
>         return VECTOR_CST_ELT (vect, index);
> -      else if (TREE_CODE (vect) == CONSTRUCTOR)
> +      else if (TREE_CODE (vect) == CONSTRUCTOR
> +              && (CONSTRUCTOR_NELTS (vect) == 0
> +                  || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
> +                     != VECTOR_TYPE))
>          {
> -          unsigned i;
> -          tree elt_i, elt_v;
> -
> -         FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (vect), i, elt_i, elt_v)
> -            if (operand_equal_p (elt_i, idx, 0))
> -              return elt_v;
> +         if (index < CONSTRUCTOR_NELTS (vect))
> +           return CONSTRUCTOR_ELT (vect, index)->value;
>            return build_zero_cst (vect_elt_type);
>          }
>        else
> @@ -1215,7 +1214,7 @@ lower_vec_perm (gimple_stmt_iterator *gs
>             t = v0_val;
>          }
>
> -      CONSTRUCTOR_APPEND_ELT (v, si, t);
> +      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
>      }
>
>    constr = build_constructor (vect_type, v);
> --- gcc/testsuite/gcc.c-torture/compile/pr54713-1.c.jj  2012-09-26 14:25:00.560733901 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr54713-1.c     2012-09-26 12:10:09.000000000 +0200
> @@ -0,0 +1,70 @@
> +/* PR tree-optimization/54713 */
> +
> +#ifndef N
> +#define N 8
> +#define ONE 1, 1, 1, 1, 1, 1, 1, 1
> +#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
> +#endif
> +
> +typedef int V __attribute__((vector_size (N * sizeof (int))));
> +typedef unsigned int W __attribute__((vector_size (N * sizeof (int))));
> +
> +void
> +f1 (V *p)
> +{
> +  *p = (*p & ((V) { ONE })) ^ ((V) { ONE});
> +}
> +
> +void
> +f2 (V *p)
> +{
> +  *p = (*p ^ ((V) { ONE })) & ((V) { ONE});
> +}
> +
> +void
> +f3 (V *p)
> +{
> +  *p = (~*p) & ((V) { ONE });
> +}
> +
> +void
> +f4 (V *p, V *q)
> +{
> +  *p = (*p ^ *q) == *q;
> +}
> +
> +void
> +f5 (V *p, V *q)
> +{
> +  *p = (*p ^ *q) == *p;
> +}
> +
> +void
> +f6 (V *p, V *q, V *r)
> +{
> +  *p = (*p & *r) == (*q & *r);
> +}
> +
> +void
> +f7 (V *p, V *q, V *r)
> +{
> +  *p = (*p & *r) == (*r & *q);
> +}
> +
> +void
> +f8 (V *p, V *q, V *r)
> +{
> +  *p = (*r & *p) == (*q & *r);
> +}
> +
> +void
> +f9 (V *p, V *q, V *r)
> +{
> +  *p = (*r & *p) == (*r & *q);
> +}
> +
> +void
> +f10 (W *p, W *q)
> +{
> +  *p = *p < (((const W) { ONEU }) << *q);
> +}
> --- gcc/testsuite/gcc.c-torture/compile/pr54713-2.c.jj  2012-09-26 14:25:03.273719043 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr54713-2.c     2012-09-26 12:11:40.000000000 +0200
> @@ -0,0 +1,7 @@
> +/* PR tree-optimization/54713 */
> +
> +#define N 16
> +#define ONE 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> +#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
> +
> +#include "pr54713-1.c"
> --- gcc/testsuite/gcc.c-torture/compile/pr54713-3.c.jj  2012-09-26 14:25:06.202702978 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr54713-3.c     2012-09-26 12:11:31.000000000 +0200
> @@ -0,0 +1,9 @@
> +/* PR tree-optimization/54713 */
> +
> +#define N 32
> +#define ONE 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
> +           1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
> +#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, \
> +            1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
> +
> +#include "pr54713-1.c"
>
>         Jakub

Patch

--- gcc/fold-const.c.jj	2012-09-25 11:59:43.000000000 +0200
+++ gcc/fold-const.c	2012-09-26 13:14:05.639000395 +0200
@@ -9559,7 +9559,7 @@  vec_cst_ctor_to_array (tree arg, tree *e
       constructor_elt *elt;
 
       FOR_EACH_VEC_ELT (constructor_elt, CONSTRUCTOR_ELTS (arg), i, elt)
-	if (i >= nelts)
+	if (i >= nelts || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
 	  return false;
 	else
 	  elts[i] = elt->value;
@@ -14030,22 +14030,35 @@  fold_ternary_loc (location_t loc, enum t
 		      unsigned i;
 		      if (CONSTRUCTOR_NELTS (arg0) == 0)
 			return build_constructor (type, NULL);
-		      vals = VEC_alloc (constructor_elt, gc, n);
-		      for (i = 0; i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
-			   ++i)
-			CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
-						CONSTRUCTOR_ELT
-						  (arg0, idx + i)->value);
-		      return build_constructor (type, vals);
+		      if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
+								 0)->value))
+			  != VECTOR_TYPE)
+			{
+			  vals = VEC_alloc (constructor_elt, gc, n);
+			  for (i = 0;
+			       i < n && idx + i < CONSTRUCTOR_NELTS (arg0);
+			       ++i)
+			    CONSTRUCTOR_APPEND_ELT (vals, NULL_TREE,
+						    CONSTRUCTOR_ELT
+						      (arg0, idx + i)->value);
+			  return build_constructor (type, vals);
+			}
 		    }
 		}
 	      else if (n == 1)
 		{
 		  if (TREE_CODE (arg0) == VECTOR_CST)
 		    return VECTOR_CST_ELT (arg0, idx);
-		  else if (idx < CONSTRUCTOR_NELTS (arg0))
-		    return CONSTRUCTOR_ELT (arg0, idx)->value;
-		  return build_zero_cst (type);
+		  else if (CONSTRUCTOR_NELTS (arg0) == 0)
+		    return build_zero_cst (type);
+		  else if (TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (arg0,
+								  0)->value))
+			   != VECTOR_TYPE)
+		    {
+		      if (idx < CONSTRUCTOR_NELTS (arg0))
+			return CONSTRUCTOR_ELT (arg0, idx)->value;
+		      return build_zero_cst (type);
+		    }
 		}
 	    }
 	}
--- gcc/tree-vect-generic.c.jj	2012-09-18 12:14:48.000000000 +0200
+++ gcc/tree-vect-generic.c	2012-09-26 14:23:40.742171292 +0200
@@ -1050,14 +1050,13 @@  vector_element (gimple_stmt_iterator *gs
 
       if (TREE_CODE (vect) == VECTOR_CST)
 	return VECTOR_CST_ELT (vect, index);
-      else if (TREE_CODE (vect) == CONSTRUCTOR)
+      else if (TREE_CODE (vect) == CONSTRUCTOR
+	       && (CONSTRUCTOR_NELTS (vect) == 0
+		   || TREE_CODE (TREE_TYPE (CONSTRUCTOR_ELT (vect, 0)->value))
+		      != VECTOR_TYPE))
         {
-          unsigned i;
-          tree elt_i, elt_v;
-
-	  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (vect), i, elt_i, elt_v)
-            if (operand_equal_p (elt_i, idx, 0))
-              return elt_v;
+	  if (index < CONSTRUCTOR_NELTS (vect))
+	    return CONSTRUCTOR_ELT (vect, index)->value;
           return build_zero_cst (vect_elt_type);
         }
       else
@@ -1215,7 +1214,7 @@  lower_vec_perm (gimple_stmt_iterator *gs
 	    t = v0_val;
         }
 
-      CONSTRUCTOR_APPEND_ELT (v, si, t);
+      CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t);
     }
 
   constr = build_constructor (vect_type, v);
--- gcc/testsuite/gcc.c-torture/compile/pr54713-1.c.jj	2012-09-26 14:25:00.560733901 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr54713-1.c	2012-09-26 12:10:09.000000000 +0200
@@ -0,0 +1,70 @@ 
+/* PR tree-optimization/54713 */
+
+#ifndef N
+#define N 8
+#define ONE 1, 1, 1, 1, 1, 1, 1, 1
+#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
+#endif
+
+typedef int V __attribute__((vector_size (N * sizeof (int))));
+typedef unsigned int W __attribute__((vector_size (N * sizeof (int))));
+
+void
+f1 (V *p)
+{
+  *p = (*p & ((V) { ONE })) ^ ((V) { ONE});
+}
+
+void
+f2 (V *p)
+{
+  *p = (*p ^ ((V) { ONE })) & ((V) { ONE});
+}
+
+void
+f3 (V *p)
+{
+  *p = (~*p) & ((V) { ONE });
+}
+
+void
+f4 (V *p, V *q)
+{
+  *p = (*p ^ *q) == *q;
+}
+
+void
+f5 (V *p, V *q)
+{
+  *p = (*p ^ *q) == *p;
+}
+
+void
+f6 (V *p, V *q, V *r)
+{
+  *p = (*p & *r) == (*q & *r);
+}
+
+void
+f7 (V *p, V *q, V *r)
+{
+  *p = (*p & *r) == (*r & *q);
+}
+
+void
+f8 (V *p, V *q, V *r)
+{
+  *p = (*r & *p) == (*q & *r);
+}
+
+void
+f9 (V *p, V *q, V *r)
+{
+  *p = (*r & *p) == (*r & *q);
+}
+
+void
+f10 (W *p, W *q)
+{
+  *p = *p < (((const W) { ONEU }) << *q);
+}
--- gcc/testsuite/gcc.c-torture/compile/pr54713-2.c.jj	2012-09-26 14:25:03.273719043 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr54713-2.c	2012-09-26 12:11:40.000000000 +0200
@@ -0,0 +1,7 @@ 
+/* PR tree-optimization/54713 */
+
+#define N 16
+#define ONE 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
+
+#include "pr54713-1.c"
--- gcc/testsuite/gcc.c-torture/compile/pr54713-3.c.jj	2012-09-26 14:25:06.202702978 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr54713-3.c	2012-09-26 12:11:31.000000000 +0200
@@ -0,0 +1,9 @@ 
+/* PR tree-optimization/54713 */
+
+#define N 32
+#define ONE 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+	    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1    
+#define ONEU 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, \
+	     1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U, 1U
+
+#include "pr54713-1.c"