]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/60276 (-O3 autovectorizer breaks on a particular loop)
authorRichard Biener <rguenther@suse.de>
Fri, 21 Feb 2014 13:18:54 +0000 (13:18 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 21 Feb 2014 13:18:54 +0000 (13:18 +0000)
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: r207992

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 2acc2dfd99f0140a55b27183a25f96e581bd8dd9..d93ac6d37d9db58ce8c44361f8e7b7c62f0b6697 100644 (file)
@@ -1,3 +1,13 @@
+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-21  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/60291
index a247f720eedfecfb16dbf5864cde3064550e7cf3..ef9d0f537974ecf9cd079387f5ff5f6c24080f95 100644 (file)
@@ -1,3 +1,8 @@
+2014-02-21  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/60276
+       * gcc.dg/vect/pr60276.c: New testcase.
+
 2014-02-21  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/60234
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 e973b34a1a79b5538f72342bad8ff8975d2c4903..fbc35a3fe3cf7085bdd50db704d9ff02ecd217fb 100644 (file)
@@ -403,6 +403,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.\n");
+         /* 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) > (unsigned)dist))
+           STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) = dist;
          continue;
        }
 
index 7e47feb61fcce1e6ea74d8962fe4a8204e7f938b..70fb411f8f5443ab89115be5998da1fb227beb9b 100644 (file)
@@ -5629,6 +5629,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;
 
@@ -5686,6 +5700,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 51367ea2500b01e26872e357c9c670b65b91604b..f8efe471e065f95a03533bec93bd067a7b341414 100644 (file)
@@ -622,6 +622,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.  */
@@ -677,6 +681,7 @@ typedef struct _stmt_vec_info {
 #define STMT_VINFO_GROUP_SAME_DR_STMT(S)   (S)->same_dr_stmt
 #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