]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: re PR tree-optimization/60276 (-O3 autovectorizer breaks on a particular...
authorRichard Biener <rguenther@suse.de>
Tue, 25 Feb 2014 12:42:59 +0000 (12:42 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Tue, 25 Feb 2014 12:42:59 +0000 (12:42 +0000)
2014-02-25  Richard Biener  <rguenther@suse.de>

Backport from mainline
2014-02-21  Richard Biener  <rguenther@suse.de>

        PR tree-optimization/60276
        * tree-vectorizer.h (struct _stmt_vec_info): Add min_neg_dist field.
        (STMT_VINFO_MIN_NEG_DIST): New macro.
        * tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Record
        STMT_VINFO_MIN_NEG_DIST.
        * tree-vect-stmts.c (vectorizable_load): Verify if assumptions
        made for negative dependence distances still hold.

        * gcc.dg/vect/pr60276.c: New testcase.

From-SVN: r208119

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr60276.c [new file with mode: 0644]
gcc/tree-vect-data-refs.c
gcc/tree-vect-stmts.c
gcc/tree-vectorizer.h

index 1bf6021ac1a238059797c379dbf2462cfe9f39e8..de0ee76b0cb91c69abbbdf8bef43aad311d41c5e 100644 (file)
@@ -1,3 +1,16 @@
+2014-02-25  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2014-02-21  Richard Biener  <rguenther@suse.de>
+
+        PR tree-optimization/60276
+        * tree-vectorizer.h (struct _stmt_vec_info): Add min_neg_dist field.
+        (STMT_VINFO_MIN_NEG_DIST): New macro.
+        * tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Record
+        STMT_VINFO_MIN_NEG_DIST.
+        * tree-vect-stmts.c (vectorizable_load): Verify if assumptions
+        made for negative dependence distances still hold.
+
 2014-02-25  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
index 9560421d0c6d2fb01376f3078d19f9e603688814..2c4743fb13821b8ae8fb9b7b9059b092a465cdd9 100644 (file)
@@ -1,3 +1,11 @@
+2014-02-25  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2014-02-21  Richard Biener  <rguenther@suse.de>
+
+        PR tree-optimization/60276
+        * gcc.dg/vect/pr60276.c: New testcase.
+
 2014-02-25  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
diff --git a/gcc/testsuite/gcc.dg/vect/pr60276.c b/gcc/testsuite/gcc.dg/vect/pr60276.c
new file mode 100644 (file)
index 0000000..d4ad219
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do run } */
+
+extern void abort (void);
+
+static void 
+foo (int *out, const int *lp, unsigned samples)
+{
+  int x, target;
+  for (x = 0, target = 0; x < (int)samples; x += 2, target++)
+    {
+      out[x] = lp[target];
+      out[x - 1] = out[x - 2] + out[x];
+    }
+}
+
+static void 
+foo_novec (int *out, const int *lp, unsigned samples)
+{
+  int x, target;
+  for (x = 0, target = 0; x < (int)samples; x += 2, target++)
+    {
+      out[x] = lp[target];
+      out[x - 1] = out[x - 2] + out[x];
+      __asm__ volatile ("" : : : "memory");
+    }
+}
+
+int main(void)
+{
+  const int lp[25] = {
+      0, 2, 4, 6, 8,
+      10, 12, 14, 16,
+      18, 20, 22, 24,
+      26, 28, 30, 32,
+      34, 36, 38, 40,
+      42, 44, 46, 48,
+  };
+  int out[49] = {0};
+  int out2[49] = {0};
+  int s;
+
+  foo (out + 2, lp + 1, 48);
+  foo_novec (out2 + 2, lp + 1, 48);
+
+  for (s = 0; s < 49; s++)
+    if (out[s] != out2[s])
+      abort ();
+
+  return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 1d5d02275453cd8836f1a1084535735071f3a6ad..bbb225ee8d63e83bce0ad5f0748bb3c8f1b52acd 100644 (file)
@@ -739,6 +739,13 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
          if (dump_enabled_p ())
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                              "dependence distance negative.");
+         /* Record a negative dependence distance to later limit the
+            amount of stmt copying / unrolling we can perform.
+            Only need to handle read-after-write dependence.  */
+         if (DR_IS_READ (drb)
+             && (STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) == 0
+                 || STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) > dist))
+           STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) = dist;
          continue;
        }
 
index 96dd191691bcae71c4bc648abb685d3f8359b839..361c312d89199f7dc37a67f002a4bdea66be167e 100644 (file)
@@ -4369,6 +4369,20 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
       return false;
     }
 
+  /* Invalidate assumptions made by dependence analysis when vectorization
+     on the unrolled body effectively re-orders stmts.  */
+  if (ncopies > 1
+      && STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
+      && ((unsigned)LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+         > STMT_VINFO_MIN_NEG_DIST (stmt_info)))
+    {
+      if (dump_enabled_p ())
+       dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                        "cannot perform implicit CSE when unrolling "
+                        "with negative dependence distance\n");
+      return false;
+    }
+
   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
     return false;
 
@@ -4425,6 +4439,20 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
          else if (!vect_grouped_load_supported (vectype, group_size))
            return false;
        }
+
+      /* Invalidate assumptions made by dependence analysis when vectorization
+        on the unrolled body effectively re-orders stmts.  */
+      if (!PURE_SLP_STMT (stmt_info)
+         && STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
+         && ((unsigned)LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+             > STMT_VINFO_MIN_NEG_DIST (stmt_info)))
+       {
+         if (dump_enabled_p ())
+           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                            "cannot perform implicit CSE when performing "
+                            "group loads with negative dependence distance\n");
+         return false;
+       }
     }
 
 
index f2ec7135a9bf50dcadd8b840abc26bc417c530f2..e4ef9934c559add63ae94ba25a92093dac909223 100644 (file)
@@ -542,6 +542,10 @@ typedef struct _stmt_vec_info {
      is 1.  */
   unsigned int gap;
 
+  /* The minimum negative dependence distance this stmt participates in
+     or zero if none.  */
+  unsigned int min_neg_dist;
+
   /* Not all stmts in the loop need to be vectorized. e.g, the increment
      of the loop induction variable and computation of array indexes. relevant
      indicates whether the stmt needs to be vectorized.  */
@@ -593,6 +597,7 @@ typedef struct _stmt_vec_info {
 #define STMT_VINFO_GROUP_READ_WRITE_DEPENDENCE(S)  (S)->read_write_dep
 #define STMT_VINFO_GROUPED_ACCESS(S)      ((S)->first_element != NULL && (S)->data_ref_info)
 #define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part
+#define STMT_VINFO_MIN_NEG_DIST(S)     (S)->min_neg_dist
 
 #define GROUP_FIRST_ELEMENT(S)          (S)->first_element
 #define GROUP_NEXT_ELEMENT(S)           (S)->next_element