2015-06-03 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Jun 2015 13:10:13 +0000 (13:10 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Jun 2015 13:10:13 +0000 (13:10 +0000)
* tree-vect-data-refs.c (vect_analyze_group_access): Properly
compute GROUP_GAP for the first element.
* tree-vect-slp.c (vect_build_slp_tree_1): Remove restriction
on in-group gaps.

* gcc.dg/vect/bb-slp-36.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@224077 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/bb-slp-36.c [new file with mode: 0644]
gcc/tree-vect-data-refs.c
gcc/tree-vect-slp.c

index cab2f38..f4d83db 100644 (file)
@@ -1,3 +1,10 @@
+2015-06-03  Richard Biener  <rguenther@suse.de>
+
+       * tree-vect-data-refs.c (vect_analyze_group_access): Properly
+       compute GROUP_GAP for the first element.
+       * tree-vect-slp.c (vect_build_slp_tree_1): Remove restriction
+       on in-group gaps.
+
 2015-06-03  Nick Clifton  <nickc@redhat.com>
 
        * config/rl78/rl78-real.md: Add peepholes to avoid a register
index 5567282..43604b7 100644 (file)
@@ -1,3 +1,7 @@
+2015-06-03  Richard Biener  <rguenther@suse.de>
+
+       * gcc.dg/vect/bb-slp-36.c: New testcase.
+
 2015-06-03  Ilya Enkovich  <ilya.enkovich@intel.com>
 
        * gcc.dg/lto/chkp-removed-alias_0.c: New.
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-36.c b/gcc/testsuite/gcc.dg/vect/bb-slp-36.c
new file mode 100644 (file)
index 0000000..f424d12
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-require-effective-target vect_int } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+
+int a[8], b[8];
+
+void __attribute__((noinline,noclone))
+foo(void)
+{
+  a[0] = b[0];
+  a[1] = b[0];
+  a[2] = b[3];
+  a[3] = b[3];
+  a[4] = b[4];
+  a[5] = b[7];
+  a[6] = b[4];
+  a[7] = b[7];
+}
+
+int main()
+{
+  int i;
+  check_vect ();
+  for (i = 0; i < 8; ++i)
+    b[i] = i;
+  foo ();
+  if (a[0] != 0 || a[1] != 0 || a[2] != 3 || a[3] != 3
+      || a[4] != 4 || a[5] != 7 || a[6] != 4 || a[7] != 7)
+    abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "basic block vectorized" "slp2" { target vect_perm } } } */
index 5c3fa3d..a019dba 100644 (file)
@@ -2205,29 +2205,33 @@ vect_analyze_group_access (struct data_reference *dr)
 
       /* Check that the size of the interleaving is equal to count for stores,
          i.e., that there are no gaps.  */
-      if (groupsize != count)
+      if (groupsize != count
+         && !DR_IS_READ (dr))
         {
-          if (DR_IS_READ (dr))
-            {
-              slp_impossible = true;
-              /* There is a gap after the last load in the group. This gap is a
-                 difference between the groupsize and the number of elements.
-                When there is no gap, this difference should be 0.  */
-              GROUP_GAP (vinfo_for_stmt (stmt)) = groupsize - count;
-            }
-          else
-            {
-              if (dump_enabled_p ())
-                dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                                 "interleaved store with gaps\n");
-              return false;
-            }
-        }
+         if (dump_enabled_p ())
+           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                            "interleaved store with gaps\n");
+         return false;
+       }
+
+      /* If there is a gap after the last load in the group it is the
+        difference between the groupsize and the last accessed
+        element.
+        When there is no gap, this difference should be 0.  */
+      GROUP_GAP (vinfo_for_stmt (stmt)) = groupsize - last_accessed_element;
 
       GROUP_SIZE (vinfo_for_stmt (stmt)) = groupsize;
       if (dump_enabled_p ())
-        dump_printf_loc (MSG_NOTE, vect_location,
-                         "Detected interleaving of size %d\n", (int)groupsize);
+       {
+         dump_printf_loc (MSG_NOTE, vect_location,
+                          "Detected interleaving of size %d starting with ",
+                          (int)groupsize);
+         dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+         if (GROUP_GAP (vinfo_for_stmt (stmt)) != 0)
+           dump_printf_loc (MSG_NOTE, vect_location,
+                            "There is a gap of %d elements after the group\n",
+                            (int)GROUP_GAP (vinfo_for_stmt (stmt)));
+       }
 
       /* SLP: create an SLP data structure for every interleaving group of
         stores for further analysis in vect_analyse_slp.  */
index 9e36d9c..5fd1635 100644 (file)
@@ -777,17 +777,13 @@ vect_build_slp_tree_1 (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
                    (*max_nunits, group_size) / group_size;
               /* FORNOW: Check that there is no gap between the loads
                 and no gap between the groups when we need to load
-                multiple groups at once.
-                ???  We should enhance this to only disallow gaps
-                inside vectors.  */
-              if ((unrolling_factor > 1
-                  && ((GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt
-                       && GROUP_GAP (vinfo_for_stmt (stmt)) != 0)
-                      /* If the group is split up then GROUP_GAP
-                         isn't correct here, nor is GROUP_FIRST_ELEMENT.  */
-                      || GROUP_SIZE (vinfo_for_stmt (stmt)) > group_size))
-                 || (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt
-                     && GROUP_GAP (vinfo_for_stmt (stmt)) != 1))
+                multiple groups at once.  */
+              if (unrolling_factor > 1
+                 && ((GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) == stmt
+                      && GROUP_GAP (vinfo_for_stmt (stmt)) != 0)
+                     /* If the group is split up then GROUP_GAP
+                        isn't correct here, nor is GROUP_FIRST_ELEMENT.  */
+                     || GROUP_SIZE (vinfo_for_stmt (stmt)) > group_size))
                 {
                   if (dump_enabled_p ())
                     {