re PR tree-optimization/59544 (Vectorizing store with negative step)
authorBingfeng Mei <bmei@broadcom.com>
Fri, 20 Dec 2013 13:46:01 +0000 (13:46 +0000)
committerBingfeng Mei <meibf@gcc.gnu.org>
Fri, 20 Dec 2013 13:46:01 +0000 (13:46 +0000)
2013-12-20  Bingfeng Mei  <bmei@broadcom.com>

PR tree-optimization/59544
* tree-vect-stmts.c (perm_mask_for_reverse): Move before
vectorizable_store.
(vectorizable_store): Handle negative step.

* gcc.target/i386/pr59544.c: New test.

From-SVN: r206148

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr59544.c [new file with mode: 0644]
gcc/tree-vect-stmts.c

index 5636956b33d6febc58e5811dcc70325441571cb2..8442c7f07a12a85a869fb141cede1a90ffba9d44 100644 (file)
@@ -1,3 +1,10 @@
+2013-12-20  Bingfeng Mei  <bmei@broadcom.com>
+
+       PR tree-optimization/59544
+       * tree-vect-stmts.c (perm_mask_for_reverse): Move before
+       vectorizable_store. 
+       (vectorizable_store): Handle negative step.
+
 2013-12-20  Tocar Ilya  <ilya.tocar@intel.com>
 
        * config.gcc: Support march=broadwell.
index 7e90641adf719f1b0db9cab8d2711bf115a74ed6..fbc6244d4dec81321b607ee2966d748cde0cebdc 100644 (file)
@@ -1,3 +1,8 @@
+2013-12-20  Bingfeng Mei  <bmei@broadcom.com>
+
+       PR tree-optimization/59544
+       * gcc.target/i386/pr59544.c: New test.
+
 2013-12-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/59413
diff --git a/gcc/testsuite/gcc.target/i386/pr59544.c b/gcc/testsuite/gcc.target/i386/pr59544.c
new file mode 100644 (file)
index 0000000..5499a53
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx -ftree-vectorize -fdump-tree-vect-details" } */
+
+void test1(short * __restrict__ x, short * __restrict__ y, short * __restrict__ z)
+{
+    int i;
+    for (i=127; i>=0; i--) {
+       x[i] = y[127-i] + z[127-i];
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 99f6b1f1ccb1f444fd1d1ca46605ae7910cdc1ba..3056c2ede0089068c9c3003ec36a3eef3b4de3af 100644 (file)
@@ -4859,6 +4859,25 @@ ensure_base_align (stmt_vec_info stmt_info, struct data_reference *dr)
 }
 
 
+/* Given a vector type VECTYPE returns the VECTOR_CST mask that implements
+   reversal of the vector elements.  If that is impossible to do,
+   returns NULL.  */
+
+static tree
+perm_mask_for_reverse (tree vectype)
+{
+  int i, nunits;
+  unsigned char *sel;
+
+  nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  sel = XALLOCAVEC (unsigned char, nunits);
+
+  for (i = 0; i < nunits; ++i)
+    sel[i] = nunits - 1 - i;
+
+  return vect_gen_perm_mask (vectype, sel);
+}
+
 /* Function vectorizable_store.
 
    Check if STMT defines a non scalar data-ref (array/pointer/structure) that
@@ -4902,6 +4921,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   vec<tree> oprnds = vNULL;
   vec<tree> result_chain = vNULL;
   bool inv_p;
+  bool negative = false;
+  tree offset = NULL_TREE;
   vec<tree> vec_oprnds = vNULL;
   bool slp = (slp_node != NULL);
   unsigned int vec_num;
@@ -4976,16 +4997,39 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
-  if (tree_int_cst_compare (loop && nested_in_vect_loop_p (loop, stmt)
-                           ? STMT_VINFO_DR_STEP (stmt_info) : DR_STEP (dr),
-                           size_zero_node) < 0)
+  negative = 
+    tree_int_cst_compare (loop && nested_in_vect_loop_p (loop, stmt)
+                         ? STMT_VINFO_DR_STEP (stmt_info) : DR_STEP (dr),
+                         size_zero_node) < 0;
+  if (negative && ncopies > 1)
     {
       if (dump_enabled_p ())
         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                         "negative step for store.\n");
+                        "multiple types with negative step.");
       return false;
     }
 
+  if (negative)
+    {
+      gcc_assert (!grouped_store);
+      alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+      if (alignment_support_scheme != dr_aligned
+         && alignment_support_scheme != dr_unaligned_supported)
+       {
+         if (dump_enabled_p ())
+           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                            "negative step but alignment required.");
+         return false;
+       }
+      if (!perm_mask_for_reverse (vectype))
+       {
+         if (dump_enabled_p ())
+           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                            "negative step and reversing not supported.");
+         return false;
+       }
+    }
+
   if (STMT_VINFO_GROUPED_ACCESS (stmt_info))
     {
       grouped_store = true;
@@ -5090,6 +5134,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
              || alignment_support_scheme == dr_aligned
              || alignment_support_scheme == dr_unaligned_supported);
 
+  if (negative)
+    offset = size_int (-TYPE_VECTOR_SUBPARTS (vectype) + 1);
+
   if (store_lanes_p)
     aggr_type = build_array_type_nelts (elem_type, vec_num * nunits);
   else
@@ -5200,7 +5247,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
            dataref_ptr
              = vect_create_data_ref_ptr (first_stmt, aggr_type,
                                          simd_lane_access_p ? loop : NULL,
-                                         NULL_TREE, &dummy, gsi, &ptr_incr,
+                                         offset, &dummy, gsi, &ptr_incr,
                                          simd_lane_access_p, &inv_p);
          gcc_assert (bb_vinfo || !inv_p);
        }
@@ -5306,6 +5353,25 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                set_ptr_info_alignment (get_ptr_info (dataref_ptr), align,
                                        misalign);
 
+             if (negative)
+               {
+                 tree perm_mask = perm_mask_for_reverse (vectype);
+                 tree perm_dest 
+                   = vect_create_destination_var (gimple_assign_rhs1 (stmt),
+                                                  vectype);
+                 tree new_temp = make_ssa_name (perm_dest, NULL);
+
+                 /* Generate the permute statement.  */
+                 gimple perm_stmt 
+                   = gimple_build_assign_with_ops (VEC_PERM_EXPR, new_temp,
+                                                   vec_oprnd, vec_oprnd,
+                                                   perm_mask);
+                 vect_finish_stmt_generation (stmt, perm_stmt, gsi);
+
+                 perm_stmt = SSA_NAME_DEF_STMT (new_temp);
+                 vec_oprnd = new_temp;
+               }
+
              /* Arguments are ready.  Create the new vector stmt.  */
              new_stmt = gimple_build_assign (data_ref, vec_oprnd);
              vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -5363,25 +5429,6 @@ vect_gen_perm_mask (tree vectype, unsigned char *sel)
   return mask_vec;
 }
 
-/* Given a vector type VECTYPE returns the VECTOR_CST mask that implements
-   reversal of the vector elements.  If that is impossible to do,
-   returns NULL.  */
-
-static tree
-perm_mask_for_reverse (tree vectype)
-{
-  int i, nunits;
-  unsigned char *sel;
-
-  nunits = TYPE_VECTOR_SUBPARTS (vectype);
-  sel = XALLOCAVEC (unsigned char, nunits);
-
-  for (i = 0; i < nunits; ++i)
-    sel[i] = nunits - 1 - i;
-
-  return vect_gen_perm_mask (vectype, sel);
-}
-
 /* Given a vector variable X and Y, that was generated for the scalar
    STMT, generate instructions to permute the vector elements of X and Y
    using permutation mask MASK_VEC, insert them at *GSI and return the