re PR tree-optimization/57051 (Optimization regression in 4.8.0 from 4.7.2)
authorJakub Jelinek <jakub@redhat.com>
Fri, 26 Apr 2013 13:13:36 +0000 (15:13 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 26 Apr 2013 13:13:36 +0000 (15:13 +0200)
PR tree-optimization/57051
* fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR
and VEC_RSHIFT_EXPR if shift count is a multiple of element
bitsize.

From-SVN: r198339

gcc/ChangeLog
gcc/fold-const.c

index dd490374f524e26f17f1fdae382c0f5ecf40384e..bd5c8f1ef0b4c521c00e9187e0d670a81449a7a0 100644 (file)
@@ -1,3 +1,10 @@
+2013-04-26  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/57051
+       * fold-const.c (const_binop): Handle VEC_LSHIFT_EXPR
+       and VEC_RSHIFT_EXPR if shift count is a multiple of element
+       bitsize.
+
 2013-04-26  Richard Biener  <rguenther@suse.de>
 
        * omp-low.c (finalize_task_copyfn): Do not drop PROP_loops.
index 59dbc034c4f3c53aa0411597e49fac67f9635437..f93ce8a7e26f204be69335a3a1f9f18c7368ca41 100644 (file)
@@ -1380,17 +1380,42 @@ const_binop (enum tree_code code, tree arg1, tree arg2)
       int count = TYPE_VECTOR_SUBPARTS (type), i;
       tree *elts = XALLOCAVEC (tree, count);
 
-      for (i = 0; i < count; i++)
+      if (code == VEC_LSHIFT_EXPR
+         || code == VEC_RSHIFT_EXPR)
        {
-         tree elem1 = VECTOR_CST_ELT (arg1, i);
-
-         elts[i] = const_binop (code, elem1, arg2);
+         if (!host_integerp (arg2, 1))
+           return NULL_TREE;
 
-         /* It is possible that const_binop cannot handle the given
-            code and return NULL_TREE */
-         if (elts[i] == NULL_TREE)
+         unsigned HOST_WIDE_INT shiftc = tree_low_cst (arg2, 1);
+         unsigned HOST_WIDE_INT outerc = tree_low_cst (TYPE_SIZE (type), 1);
+         unsigned HOST_WIDE_INT innerc
+           = tree_low_cst (TYPE_SIZE (TREE_TYPE (type)), 1);
+         if (shiftc >= outerc || (shiftc % innerc) != 0)
            return NULL_TREE;
+         int offset = shiftc / innerc;
+         if (code == VEC_LSHIFT_EXPR)
+           offset = -offset;
+         tree zero = build_zero_cst (TREE_TYPE (type));
+         for (i = 0; i < count; i++)
+           {
+             if (i + offset < 0 || i + offset >= count)
+               elts[i] = zero;
+             else
+               elts[i] = VECTOR_CST_ELT (arg1, i + offset);
+           }
        }
+      else
+       for (i = 0; i < count; i++)
+         {
+           tree elem1 = VECTOR_CST_ELT (arg1, i);
+
+           elts[i] = const_binop (code, elem1, arg2);
+
+           /* It is possible that const_binop cannot handle the given
+              code and return NULL_TREE */
+           if (elts[i] == NULL_TREE)
+             return NULL_TREE;
+         }
 
       return build_vector (type, elts);
     }