Thank you for your reminder, Jeff! I just noticed Richard's comment. I
have modified the patch according to that.

The new patch is attached.


thanks,
Cong


On Tue, Oct 15, 2013 at 12:33 PM, Jeff Law <l...@redhat.com> wrote:
> On 10/14/13 17:31, Cong Hou wrote:
>>
>> Any comment on this patch?
>
> Richi replied in the BZ you opened.
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58508
>
> Essentially he said emit the load on the edge rather than in the block
> itself.
> jeff
>
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8a38316..2637309 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2013-10-15  Cong Hou  <co...@google.com>
+
+       * tree-vect-loop-manip.c (vect_loop_versioning): Hoist loop invariant
+       statement that contains data refs with zero-step.
+
 2013-10-14  David Malcolm  <dmalc...@redhat.com>
 
        * dumpfile.h (gcc::dump_manager): New class, to hold state
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 075d071..9d0f4a5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2013-10-15  Cong Hou  <co...@google.com>
+
+       * gcc.dg/vect/pr58508.c: New test.
+
 2013-10-14  Tobias Burnus  <bur...@net-b.de>
 
        PR fortran/58658
diff --git a/gcc/testsuite/gcc.dg/vect/pr58508.c 
b/gcc/testsuite/gcc.dg/vect/pr58508.c
new file mode 100644
index 0000000..cb22b50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr58508.c
@@ -0,0 +1,20 @@
+/* { 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 foo (int* a, int* b)
+{
+  int i;
+  for (i = 0; i < 100000; ++i)
+    a[i] = *b + 1;
+}
+
+
+/* { dg-final { scan-tree-dump-times "hoist" 2 "vect" } } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 574446a..f4fdec2 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -2477,6 +2477,92 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
       adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
     }
 
+
+  /* Extract load and store statements on pointers 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
+        or store.  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, and move the store statement to the loop exit.  */
+
+      for (gimple_stmt_iterator si = gsi_start_bb (loop->header);
+          !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 (dr && integer_zerop (DR_STEP (dr)))
+           {
+             if (DR_IS_READ (dr))
+               {
+                 if (dump_enabled_p ())
+                   {
+                     dump_printf_loc
+                         (MSG_NOTE, vect_location,
+                          "hoist the statement to outside of the loop ");
+                     dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0);
+                     dump_printf (MSG_NOTE, "\n");
+                   }
+
+                 gsi_remove (&si, false);
+                 gsi_insert_on_edge_immediate (loop_preheader_edge (loop), 
stmt);
+               }
+             /* TODO: We also consider vectorizing loops containing zero-step
+                data refs as writes.  For example:
+
+                int a[N], *s;
+                for (i = 0; i < N; i++)
+                  *s += a[i];
+
+                In this case the write to *s can be also moved after the
+                loop.  */
+
+             continue;
+           }
+         else if (!dr)
+         {
+           bool hoist = true;
+           for (size_t i = 0; i < gimple_num_ops (stmt); i++)
+             {
+               tree op = gimple_op (stmt, i);
+               if (TREE_CODE (op) == INTEGER_CST
+                   || TREE_CODE (op) == REAL_CST)
+                 continue;
+               if (TREE_CODE (op) == SSA_NAME)
+                 {
+                   gimple def = SSA_NAME_DEF_STMT (op);
+                   if (def == stmt
+                       || gimple_nop_p (def)
+                       || !flow_bb_inside_loop_p (loop, gimple_bb (def)))
+                     continue;
+                 }
+               hoist = false;
+               break;
+             }
+
+           if (hoist)
+             {
+               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,
+                        "hoist the statement to outside of the 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)

Reply via email to