On Thu, Apr 25, 2013 at 11:47:02PM +0200, Jakub Jelinek wrote:
> This patch adds folding of constant arguments v>> and v<<, which helps to
> optimize the testcase from the PR back into constant store after vectorized
> loop is unrolled.

As this fixes a regression on the 4.8 branch, I've backported it (and
minimal prerequisite for that) to 4.8 branch too.

As the non-whole vector shifts VECTOR_CST by INTEGER_CST don't have any
testcase showing a regression, I've left those out (trunk has instead
of that else return NULL_TREE; code to handle those).

2013-05-03  Jakub Jelinek  <ja...@redhat.com>

        Backported from mainline
        2013-04-26  Jakub Jelinek  <ja...@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-12  Marc Glisse  <marc.gli...@inria.fr>

        * fold-const.c (fold_binary_loc): Call const_binop also for mixed
        vector-scalar operations.

--- gcc/fold-const.c    (revision 198579)
+++ gcc/fold-const.c    (working copy)
@@ -1366,6 +1366,44 @@ const_binop (enum tree_code code, tree a
 
       return build_vector (type, elts);
     }
+
+  /* Shifts allow a scalar offset for a vector.  */
+  if (TREE_CODE (arg1) == VECTOR_CST
+      && TREE_CODE (arg2) == INTEGER_CST)
+    {
+      tree type = TREE_TYPE (arg1);
+      int count = TYPE_VECTOR_SUBPARTS (type), i;
+      tree *elts = XALLOCAVEC (tree, count);
+
+      if (code == VEC_LSHIFT_EXPR
+         || code == VEC_RSHIFT_EXPR)
+       {
+         if (!host_integerp (arg2, 1))
+           return 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
+       return NULL_TREE;
+
+      return build_vector (type, elts);
+    }
   return NULL_TREE;
 }
 
@@ -9862,7 +9900,8 @@ fold_binary_loc (location_t loc,
       || (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == FIXED_CST)
       || (TREE_CODE (arg0) == FIXED_CST && TREE_CODE (arg1) == INTEGER_CST)
       || (TREE_CODE (arg0) == COMPLEX_CST && TREE_CODE (arg1) == COMPLEX_CST)
-      || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST))
+      || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
+      || (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == INTEGER_CST))
     {
       if (kind == tcc_binary)
        {


        Jakub

Reply via email to