re PR tree-optimization/60276 (-O3 autovectorizer breaks on a particular loop)

2014-02-21  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/60276
	* tree-vectorizer.h (struct _stmt_vec_info): Add min_neg_dist field.
	(STMT_VINFO_MIN_NEG_DIST): New macro.
	* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Record
	STMT_VINFO_MIN_NEG_DIST.
	* tree-vect-stmts.c (vectorizable_load): Verify if assumptions
	made for negative dependence distances still hold.

	* gcc.dg/vect/pr60276.c: New testcase.

From-SVN: r207992
This commit is contained in:
Richard Biener 2014-02-21 13:18:54 +00:00 committed by Richard Biener
parent 32417082bf
commit f2556b68ca
6 changed files with 107 additions and 0 deletions

View File

@ -1,3 +1,13 @@
2014-02-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/60276
* tree-vectorizer.h (struct _stmt_vec_info): Add min_neg_dist field.
(STMT_VINFO_MIN_NEG_DIST): New macro.
* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Record
STMT_VINFO_MIN_NEG_DIST.
* tree-vect-stmts.c (vectorizable_load): Verify if assumptions
made for negative dependence distances still hold.
2014-02-21 Richard Biener <rguenther@suse.de>
PR middle-end/60291

View File

@ -1,3 +1,8 @@
2014-02-21 Richard Biener <rguenther@suse.de>
PR tree-optimization/60276
* gcc.dg/vect/pr60276.c: New testcase.
2014-02-21 Janus Weil <janus@gcc.gnu.org>
PR fortran/60234

View File

@ -0,0 +1,52 @@
/* { dg-do run } */
extern void abort (void);
static void
foo (int *out, const int *lp, unsigned samples)
{
int x, target;
for (x = 0, target = 0; x < (int)samples; x += 2, target++)
{
out[x] = lp[target];
out[x - 1] = out[x - 2] + out[x];
}
}
static void
foo_novec (int *out, const int *lp, unsigned samples)
{
int x, target;
for (x = 0, target = 0; x < (int)samples; x += 2, target++)
{
out[x] = lp[target];
out[x - 1] = out[x - 2] + out[x];
__asm__ volatile ("" : : : "memory");
}
}
int main(void)
{
const int lp[25] = {
0, 2, 4, 6, 8,
10, 12, 14, 16,
18, 20, 22, 24,
26, 28, 30, 32,
34, 36, 38, 40,
42, 44, 46, 48,
};
int out[49] = {0};
int out2[49] = {0};
int s;
foo (out + 2, lp + 1, 48);
foo_novec (out2 + 2, lp + 1, 48);
for (s = 0; s < 49; s++)
if (out[s] != out2[s])
abort ();
return 0;
}
/* { dg-final { cleanup-tree-dump "vect" } } */

View File

@ -403,6 +403,13 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"dependence distance negative.\n");
/* Record a negative dependence distance to later limit the
amount of stmt copying / unrolling we can perform.
Only need to handle read-after-write dependence. */
if (DR_IS_READ (drb)
&& (STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) == 0
|| STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) > (unsigned)dist))
STMT_VINFO_MIN_NEG_DIST (stmtinfo_b) = dist;
continue;
}

View File

@ -5629,6 +5629,20 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
}
/* Invalidate assumptions made by dependence analysis when vectorization
on the unrolled body effectively re-orders stmts. */
if (ncopies > 1
&& STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
&& ((unsigned)LOOP_VINFO_VECT_FACTOR (loop_vinfo)
> STMT_VINFO_MIN_NEG_DIST (stmt_info)))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"cannot perform implicit CSE when unrolling "
"with negative dependence distance\n");
return false;
}
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
@ -5686,6 +5700,20 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
else if (!vect_grouped_load_supported (vectype, group_size))
return false;
}
/* Invalidate assumptions made by dependence analysis when vectorization
on the unrolled body effectively re-orders stmts. */
if (!PURE_SLP_STMT (stmt_info)
&& STMT_VINFO_MIN_NEG_DIST (stmt_info) != 0
&& ((unsigned)LOOP_VINFO_VECT_FACTOR (loop_vinfo)
> STMT_VINFO_MIN_NEG_DIST (stmt_info)))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"cannot perform implicit CSE when performing "
"group loads with negative dependence distance\n");
return false;
}
}

View File

@ -622,6 +622,10 @@ typedef struct _stmt_vec_info {
is 1. */
unsigned int gap;
/* The minimum negative dependence distance this stmt participates in
or zero if none. */
unsigned int min_neg_dist;
/* Not all stmts in the loop need to be vectorized. e.g, the increment
of the loop induction variable and computation of array indexes. relevant
indicates whether the stmt needs to be vectorized. */
@ -677,6 +681,7 @@ typedef struct _stmt_vec_info {
#define STMT_VINFO_GROUP_SAME_DR_STMT(S) (S)->same_dr_stmt
#define STMT_VINFO_GROUPED_ACCESS(S) ((S)->first_element != NULL && (S)->data_ref_info)
#define STMT_VINFO_LOOP_PHI_EVOLUTION_PART(S) (S)->loop_phi_evolution_part
#define STMT_VINFO_MIN_NEG_DIST(S) (S)->min_neg_dist
#define GROUP_FIRST_ELEMENT(S) (S)->first_element
#define GROUP_NEXT_ELEMENT(S) (S)->next_element