aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorCong Hou <congh@google.com>2013-10-19 01:20:24 -0400
committerJeff Law <law@gcc.gnu.org>2013-10-18 23:20:24 -0600
commit6f978a2a7834fa96f1899cf41f56f15509d34cf3 (patch)
treea69cb657131a63bd426e8172939dd8d8c19ce8c3 /gcc
parent6b8fe121affbf6fcfe19fca582c56cb9baf9b600 (diff)
downloadgcc-6f978a2a7834fa96f1899cf41f56f15509d34cf3.zip
gcc-6f978a2a7834fa96f1899cf41f56f15509d34cf3.tar.gz
gcc-6f978a2a7834fa96f1899cf41f56f15509d34cf3.tar.bz2
re PR tree-optimization/58508 ([Missed-Optimization] Redundant vector load of "actual" loop invariant in loop body.)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr58508.c70
-rw-r--r--gcc/tree-vect-loop-manip.c67
4 files changed, 147 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 93a357a..bdb9e01 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 823b8ef..646a97a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..6484a65
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr58508.c
@@ -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" } } */
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 574446a..1cc563c 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -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)