mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
6b8fe121af
commit
6f978a2a78
|
|
@ -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>
|
2013-10-18 Andrew MacLeod <amacleod@redhat.com>
|
||||||
|
|
||||||
* tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h, sbitmap.h,
|
* tree-ssa.h: Don't include gimple-low.h, tree-ssa-address.h, sbitmap.h,
|
||||||
|
|
|
||||||
|
|
@ -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>
|
2013-10-18 Paolo Carlini <paolo.carlini@oracle.com>
|
||||||
|
|
||||||
PR c++/58466
|
PR c++/58466
|
||||||
|
|
|
||||||
|
|
@ -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" } } */
|
||||||
|
|
@ -2477,6 +2477,73 @@ vect_loop_versioning (loop_vec_info loop_vinfo,
|
||||||
adjust_phi_and_debug_stmts (orig_phi, e, PHI_RESULT (new_phi));
|
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. */
|
/* End loop-exit-fixes after versioning. */
|
||||||
|
|
||||||
if (cond_expr_stmt_list)
|
if (cond_expr_stmt_list)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue