[Bug tree-optimization/58508] New: Redundant vector load of "actual" loop invariant in loop body.
congh at google dot com
gcc-bugzilla@gcc.gnu.org
Mon Sep 23 18:23:00 GMT 2013
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58508
Bug ID: 58508
Summary: Redundant vector load of "actual" loop invariant in
loop body.
Product: gcc
Version: 4.9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: congh at google dot com
When GCC vectorizes the loop below, it will firstly do loop versioning with
aliasing check on a and b. Since a and b have different strides (1 and 0), the
check guarantees that there is no aliasing between a and b across all
iterations. Then with this precondition *b becomes a loop invariant so that it
can be loaded outside the loop during vectorization (Note that this
precondition always holds when the loop is being vectorized). This can save us
a load and a shuffle instruction in each iteration.
void foo (int* a, int* b, int n)
{
for (int i = 0; i < n; ++i)
a[i] += *b;
}
I have a patch handling this case as an optimization. After loop versioning, I
detect all zero-strided data references and hoist the loads of them to the loop
header. The patch is shown below.
thanks,
Cong
Index: gcc/tree-vect-loop-manip.c
===================================================================
--- gcc/tree-vect-loop-manip.c (revision 202662)
+++ gcc/tree-vect-loop-manip.c (working copy)
@@ -2477,6 +2477,37 @@ vect_loop_versioning (loop_vec_info loop
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))
+ {
+ basic_block preheader = loop_preheader_edge (loop)->src;
+ gimple_stmt_iterator si_dst = gsi_last_bb (preheader);
+ gsi_move_after (&si, &si_dst);
+ }
+ }
+ else
+ gsi_next (&si);
+ }
+ }
+
/* End loop-exit-fixes after versioning. */
if (cond_expr_stmt_list)
More information about the Gcc-bugs
mailing list