This fixes the wrong-code caused by the use-before-compute of GROUP_READ_WRITE_DEPENDENCE after I moved data dependence checking after group analysis in the vectorizer. The fix is to move the dependence checking completely to the dependence checking - now possible as we have computed groups already.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied. Richard. 2013-04-15 Richard Biener <rguent...@suse.de> PR tree-optimization/56933 * tree-vectorizer.h (struct _stmt_vec_info): Remove read_write_dep member. (GROUP_READ_WRITE_DEPENDENCE): Remove. (STMT_VINFO_GROUP_READ_WRITE_DEPENDENCE): Likewise. * tree-vect-data-refs.c (vect_analyze_group_access): Move dependence check ... vect_analyze_data_ref_dependence (vect_analyze_data_ref_dependence): ... here. * tree-vect-stmts.c (new_stmt_vec_info): Do not initialize GROUP_READ_WRITE_DEPENDENCE. * gcc.dg/vect/pr56933.c: New testcase. Index: gcc/tree-vect-data-refs.c =================================================================== *** gcc/tree-vect-data-refs.c (revision 197957) --- gcc/tree-vect-data-refs.c (working copy) *************** vect_analyze_data_ref_dependence (struct *** 341,354 **** dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb)); } ! /* For interleaving, mark that there is a read-write dependency if ! necessary. We check before that one of the data-refs is store. */ ! if (DR_IS_READ (dra)) ! GROUP_READ_WRITE_DEPENDENCE (stmtinfo_a) = true; ! else ! { ! if (DR_IS_READ (drb)) ! GROUP_READ_WRITE_DEPENDENCE (stmtinfo_b) = true; } continue; --- 341,374 ---- dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (drb)); } ! /* When we perform grouped accesses and perform implicit CSE ! by detecting equal accesses and doing disambiguation with ! runtime alias tests like for ! .. = a[i]; ! .. = a[i+1]; ! a[i] = ..; ! a[i+1] = ..; ! *p = ..; ! .. = a[i]; ! .. = a[i+1]; ! where we will end up loading { a[i], a[i+1] } once, make ! sure that inserting group loads before the first load and ! stores after the last store will do the right thing. */ ! if ((STMT_VINFO_GROUPED_ACCESS (stmtinfo_a) ! && GROUP_SAME_DR_STMT (stmtinfo_a)) ! || (STMT_VINFO_GROUPED_ACCESS (stmtinfo_b) ! && GROUP_SAME_DR_STMT (stmtinfo_b))) ! { ! gimple earlier_stmt; ! earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb)); ! if (DR_IS_WRITE ! (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt)))) ! { ! if (dump_enabled_p ()) ! dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, ! "READ_WRITE dependence in interleaving."); ! return true; ! } } continue; *************** vect_analyze_group_access (struct data_r *** 2097,2113 **** return false; } - /* Check that there is no load-store dependencies for this loads - to prevent a case of load-store-load to the same location. */ - if (GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (next)) - || GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (prev))) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "READ_WRITE dependence in interleaving."); - return false; - } - /* For load use the same data-ref load. */ GROUP_SAME_DR_STMT (vinfo_for_stmt (next)) = prev; --- 2117,2122 ---- Index: gcc/tree-vect-stmts.c =================================================================== *** gcc/tree-vect-stmts.c (revision 197957) --- gcc/tree-vect-stmts.c (working copy) *************** new_stmt_vec_info (gimple stmt, loop_vec *** 5962,5968 **** GROUP_STORE_COUNT (res) = 0; GROUP_GAP (res) = 0; GROUP_SAME_DR_STMT (res) = NULL; - GROUP_READ_WRITE_DEPENDENCE (res) = false; return res; } --- 5962,5967 ---- Index: gcc/tree-vectorizer.h =================================================================== *** gcc/tree-vectorizer.h (revision 197957) --- gcc/tree-vectorizer.h (working copy) *************** typedef struct _stmt_vec_info { *** 460,469 **** /* Stmt is part of some pattern (computation idiom) */ bool in_pattern_p; - /* For loads only, if there is a store with the same location, this field is - TRUE. */ - bool read_write_dep; - /* The stmt to which this info struct refers to. */ gimple stmt; --- 460,465 ---- *************** typedef struct _stmt_vec_info { *** 589,595 **** #define STMT_VINFO_GROUP_STORE_COUNT(S) (S)->store_count #define STMT_VINFO_GROUP_GAP(S) (S)->gap #define STMT_VINFO_GROUP_SAME_DR_STMT(S) (S)->same_dr_stmt - #define STMT_VINFO_GROUP_READ_WRITE_DEPENDENCE(S) (S)->read_write_dep #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 --- 585,590 ---- *************** typedef struct _stmt_vec_info { *** 599,605 **** #define GROUP_STORE_COUNT(S) (S)->store_count #define GROUP_GAP(S) (S)->gap #define GROUP_SAME_DR_STMT(S) (S)->same_dr_stmt - #define GROUP_READ_WRITE_DEPENDENCE(S) (S)->read_write_dep #define STMT_VINFO_RELEVANT_P(S) ((S)->relevant != vect_unused_in_scope) --- 594,599 ---- Index: gcc/testsuite/gcc.dg/vect/pr56933.c =================================================================== *** gcc/testsuite/gcc.dg/vect/pr56933.c (revision 0) --- gcc/testsuite/gcc.dg/vect/pr56933.c (working copy) *************** *** 0 **** --- 1,40 ---- + /* { dg-do run } */ + + extern void abort (void); + void __attribute__((noinline,noclone)) + foo (double *b, double *d, double *f) + { + int i; + for (i = 0; i < 1024; i++) + { + d[2*i] = 2. * d[2*i]; + d[2*i+1] = 4. * d[2*i+1]; + b[i] = d[2*i] - 1.; + f[i] = d[2*i+1] + 2.; + } + } + int main() + { + double b[1024], d[2*1024], f[1024]; + int i; + for (i = 0; i < 2*1024; i++) + d[i] = 1.; + foo (b, d, f); + for (i = 0; i < 1024; i+= 2) + { + if (d[2*i] != 2.) + abort (); + if (d[2*i+1] != 4.) + abort (); + } + for (i = 0; i < 1024; i++) + { + if (b[i] != 1.) + abort (); + if (f[i] != 6.) + abort (); + } + return 0; + } + + /* { dg-final { cleanup-tree-dump "vect" } } */