]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/58508 ([Missed-Optimization] Redundant vector load of "actual...
authorCong Hou <congh@google.com>
Sat, 19 Oct 2013 05:20:24 +0000 (01:20 -0400)
committerJeff Law <law@gcc.gnu.org>
Sat, 19 Oct 2013 05:20:24 +0000 (23:20 -0600)
PR tree-optimization/58508
* tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant
statement that contains data refs with zero-step.

* gcc.dg/vect/pr58508.c: New test.

From-SVN: r203842

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr58508.c [new file with mode: 0644]
gcc/tree-vect-loop-manip.c

index 93a357a7481e55e821655073b6bec7fd56d4dc08..bdb9e01c6012a50a16086080a6d794d029edbbc8 100644 (file)
@@ -1,3 +1,9 @@
+2013-10-18  Cong Hou  <congh@google.com>
+
+       PR tree-optimization/58508
+       * tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant
+       statement that contains data refs with zero-step.
+
 2013-10-18  Andrew MacLeod  <amacleod@redhat.com>
 
        * tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h, sbitmap.h,
index 823b8efee3eb7c8ef9ea29783af0ff0dc9b3bebd..646a97ab45920dfc6ae7ba26d1e411815f2884d0 100644 (file)
@@ -1,3 +1,7 @@
+2013-10-18  Cong Hou  <congh@google.com>
+
+       * gcc.dg/vect/pr58508.c: New test.
+
 2013-10-18  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/58466
diff --git a/gcc/testsuite/gcc.dg/vect/pr58508.c b/gcc/testsuite/gcc.dg/vect/pr58508.c
new file mode 100644 (file)
index 0000000..6484a65
--- /dev/null
@@ -0,0 +1,70 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */
+
+
+/* The GCC vectorizer generates loop versioning for the following loop
+   since there may exist aliasing between A and B.  The predicate checks
+   if A may alias with B across all iterations.  Then for the loop in
+   the true body, we can assert that *B is a loop invariant so that
+   we can hoist the load of *B before the loop body.  */
+
+void test1 (int* a, int* b)
+{
+  int i;
+  for (i = 0; i < 100000; ++i)
+    a[i] = *b + 1;
+}
+
+/* A test case with nested loops.  The load of b[j+1] in the inner
+   loop should be hoisted.  */
+
+void test2 (int* a, int* b)
+{
+  int i, j;
+  for (j = 0; j < 100000; ++j)
+    for (i = 0; i < 100000; ++i)
+      a[i] = b[j+1] + 1;
+}
+
+/* A test case with ifcvt transformation.  */
+
+void test3 (int* a, int* b)
+{
+  int i, t;
+  for (i = 0; i < 10000; ++i)
+    {
+      if (*b > 0)
+       t = *b * 2;
+      else
+       t = *b / 2;
+      a[i] = t;
+    }
+}
+
+/* A test case in which the store in the loop can be moved outside
+   in the versioned loop with alias checks.  Note this loop won't
+   be vectorized.  */
+
+void test4 (int* a, int* b)
+{
+  int i;
+  for (i = 0; i < 100000; ++i)
+    *a += b[i];
+}
+
+/* A test case in which the load and store in the loop to b
+   can be moved outside in the versioned loop with alias checks.
+   Note this loop won't be vectorized.  */
+
+void test5 (int* a, int* b)
+{
+  int i;
+  for (i = 0; i < 100000; ++i)
+    {
+      *b += a[i];
+      a[i] = *b;
+    }
+}
+
+/* { dg-final { scan-tree-dump-times "hoist" 8 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 574446a7ddec0cfb6b3b300e27e051656b30e4d7..1cc563c3cbbd99226254cb1ced272ecfe88a4c6e 100644 (file)
@@ -2477,6 +2477,73 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
       adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
     }
 
+
+  /* Extract load statements on memrefs with zero-stride accesses.  */
+
+  if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
+    {
+      /* In the loop body, we iterate each statement to check if it is a load.
+        Then we check the DR_STEP of the data reference.  If DR_STEP is zero,
+        then we will hoist the load statement to the loop preheader.  */
+
+      basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
+      int nbbs = loop->num_nodes;
+
+      for (int i = 0; i < nbbs; ++i)
+       {
+         for (gimple_stmt_iterator si = gsi_start_bb (bbs[i]);
+              !gsi_end_p (si);)
+           {
+             gimple stmt = gsi_stmt (si);
+             stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+             struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
+
+             if (is_gimple_assign (stmt)
+                 && (!dr
+                     || (DR_IS_READ (dr) && integer_zerop (DR_STEP (dr)))))
+               {
+                 bool hoist = true;
+                 ssa_op_iter iter;
+                 tree var;
+
+                 /* We hoist a statement if all SSA uses in it are defined
+                    outside of the loop.  */
+                 FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
+                   {
+                     gimple def = SSA_NAME_DEF_STMT (var);
+                     if (!gimple_nop_p (def)
+                         && flow_bb_inside_loop_p (loop, gimple_bb (def)))
+                       {
+                         hoist = false;
+                         break;
+                       }
+                   }
+
+                 if (hoist)
+                   {
+                     if (dr)
+                       gimple_set_vuse (stmt, NULL);
+
+                     gsi_remove (&si, false);
+                     gsi_insert_on_edge_immediate (loop_preheader_edge (loop),
+                                                   stmt);
+
+                     if (dump_enabled_p ())
+                       {
+                         dump_printf_loc
+                             (MSG_NOTE, vect_location,
+                              "hoisting out of the vectorized loop: ");
+                         dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+                         dump_printf (MSG_NOTE, "\n");
+                       }
+                     continue;
+                   }
+               }
+             gsi_next (&si);
+           }
+       }
+    }
+
   /* End loop-exit-fixes after versioning.  */
 
   if (cond_expr_stmt_list)