diff mbox series

Fix PR87665

Message ID alpine.LSU.2.20.1810231604450.4374@zhemvz.fhfr.qr
State New
Headers show
Series Fix PR87665 | expand

Commit Message

Richard Biener Oct. 23, 2018, 2:07 p.m. UTC
The following fixes a long-standing issue with SLP vectorization
where the dependence checking didn't really reflect reality... (oops).

I have sofar prepared trunk and GCC 8 variants.

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Richard.

2018-10-23  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/87665
	* tree-vect-data-refs.c (vect_preserves_scalar_order_p): Adjust
	to reflect reality.

	* gcc.dg/torture/pr87665.c: New testcase.
diff mbox series

Patch

Index: gcc/tree-vect-data-refs.c
===================================================================
--- gcc/tree-vect-data-refs.c	(revision 265422)
+++ gcc/tree-vect-data-refs.c	(working copy)
@@ -210,16 +210,26 @@  vect_preserves_scalar_order_p (dr_vec_in
     return true;
 
   /* STMT_A and STMT_B belong to overlapping groups.  All loads in a
-     group are emitted at the position of the first scalar load and all
+     group are emitted at the position of the last scalar load and all
      stores in a group are emitted at the position of the last scalar store.
-     Thus writes will happen no earlier than their current position
-     (but could happen later) while reads will happen no later than their
-     current position (but could happen earlier).  Reordering is therefore
-     only possible if the first access is a write.  */
-  stmtinfo_a = vect_orig_stmt (stmtinfo_a);
-  stmtinfo_b = vect_orig_stmt (stmtinfo_b);
-  stmt_vec_info earlier_stmt_info = get_earlier_stmt (stmtinfo_a, stmtinfo_b);
-  return !DR_IS_WRITE (STMT_VINFO_DATA_REF (earlier_stmt_info));
+     Compute that position and check whether the resulting order matches
+     the current one.  */
+  stmt_vec_info last_a = DR_GROUP_FIRST_ELEMENT (stmtinfo_a);
+  if (last_a)
+    for (stmt_vec_info s = DR_GROUP_NEXT_ELEMENT (last_a); s;
+	 s = DR_GROUP_NEXT_ELEMENT (s))
+      last_a = get_later_stmt (last_a, s);
+  else
+    last_a = stmtinfo_a;
+  stmt_vec_info last_b = DR_GROUP_FIRST_ELEMENT (stmtinfo_b);
+  if (last_b)
+    for (stmt_vec_info s = DR_GROUP_NEXT_ELEMENT (last_b); s;
+	 s = DR_GROUP_NEXT_ELEMENT (s))
+      last_b = get_later_stmt (last_b, s);
+  else
+    last_b = stmtinfo_b;
+  return ((get_later_stmt (last_a, last_b) == last_a)
+	  == (get_later_stmt (stmtinfo_a, stmtinfo_b) == stmtinfo_a));
 }
 
 /* A subroutine of vect_analyze_data_ref_dependence.  Handle
Index: gcc/testsuite/gcc.dg/torture/pr87665.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr87665.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr87665.c	(working copy)
@@ -0,0 +1,27 @@ 
+/* { dg-do run } */
+
+struct X { long x; long y; };
+
+struct X a[1024], b[1024];
+
+void foo ()
+{
+  for (int i = 0; i < 1024; ++i)
+    {
+      long tem = a[i].x;
+      a[i].x = 0;
+      b[i].x = tem;
+      b[i].y = a[i].y;
+    }
+}
+
+int main()
+{
+  for (int i = 0; i < 1024; ++i)
+    a[i].x = i;
+  foo ();
+  for (int i = 0; i < 1024; ++i)
+    if (b[i].x != i)
+      __builtin_abort();
+  return 0;
+}