diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 62680caf704..de0752707b2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2007-01-21 Ira Rosen + + * tree-vectorizer.h (struct _stmt_vec_info): Add new field + read_write_dep and macros for its access. + * tree-vectorizer.c (new_stmt_vec_info): Initialize the new field. + * tree-vect-analyze.c (vect_analyze_data_ref_dependence): Remove + argument, call vect_check_interleaving for every independent pair of + data-refs. Mark loads that access the same memory location as a store + in the loop. + (vect_check_dependences): Remove. + (vect_analyze_data_ref_dependences): Remove vect_check_dependences + call, fix the call to vect_analyze_data_ref_dependence. + (vect_analyze_data_ref_access): For statements that access the same + data-ref, check that they are not stores; for loads, check that there + is no store that access the same location. + 2007-01-20 Roger Sayle Joseph Myers diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 320c9020359..d248286770e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2007-01-21 Ira Rosen + + * gcc.dg/vect/vect-strided-same-dr.c: New test. + 2007-01-20 Andrew Pinski PR objc/30479 diff --git a/gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c b/gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c new file mode 100644 index 00000000000..f04658d1d07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c @@ -0,0 +1,77 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 128 + +typedef struct { + unsigned short a; + unsigned short b; +} s; + +s buffer1[N], buffer2[N]; + +int +main1 (s * __restrict__ pIn, s* __restrict__ pOut) +{ + unsigned short i, x, y, d; + s *p, *q; + + p = pIn; + q = pOut; + + for (i = 0; i < N/2; i++) + { + x = pIn->a + 5; + y = pIn->a + 2; + pOut->a = x; + pOut->b = pIn->b; + pOut++; + pOut->a = y; + pOut->b = pIn->b; + pOut++; + pIn++; + } + + /* check results: */ + for (i = 0; i < N/2; i++) + { + if (q->a != p->a + 5 + || q->b != p->b) + abort (); + q++; + if (q->a != p->a + 2 + || q->b != p->b) + abort (); + q++; + p++; + } + + return 0; +} + +int main (void) +{ + short i; + + for (i = 0; i < N*2; i++) + { + buffer1[i].a = i; + buffer1[i].b = i + 8; + buffer2[i].a = i * 3; + buffer2[i].b = i * 2; + if (buffer1[i].a == 500) + abort(); + } + + check_vect (); + + main1 (buffer1, buffer2); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 114f8236a6c..c53c34e2c51 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -57,7 +57,7 @@ static bool vect_determine_vectorization_factor (loop_vec_info); static bool exist_non_indexing_operands_for_use_p (tree, tree); static tree vect_get_loop_niters (struct loop *, tree *); static bool vect_analyze_data_ref_dependence - (struct data_dependence_relation *, loop_vec_info, bool); + (struct data_dependence_relation *, loop_vec_info); static bool vect_compute_data_ref_alignment (struct data_reference *); static bool vect_analyze_data_ref_access (struct data_reference *); static bool vect_can_advance_ivs_p (loop_vec_info); @@ -877,8 +877,7 @@ vect_check_interleaving (struct data_reference *dra, static bool vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, - loop_vec_info loop_vinfo, - bool check_interleaving) + loop_vec_info loop_vinfo) { unsigned int i; struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); @@ -895,8 +894,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (DDR_ARE_DEPENDENT (ddr) == chrec_known) { /* Independent data accesses. */ - if (check_interleaving) - vect_check_interleaving (dra, drb); + vect_check_interleaving (dra, drb); return false; } @@ -951,7 +949,18 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, fprintf (vect_dump, " and "); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); } - continue; + + /* 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)) + DR_GROUP_READ_WRITE_DEPENDENCE (stmtinfo_a) = true; + else + { + if (DR_IS_READ (drb)) + DR_GROUP_READ_WRITE_DEPENDENCE (stmtinfo_b) = true; + } + + continue; } if (abs (dist) >= vectorization_factor) @@ -979,36 +988,6 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, } -/* Function vect_check_dependences. - - Return TRUE if there is a store-store or load-store dependence between - data-refs in DDR, otherwise return FALSE. */ - -static bool -vect_check_dependences (struct data_dependence_relation *ddr) -{ - struct data_reference *dra = DDR_A (ddr); - struct data_reference *drb = DDR_B (ddr); - - if (DDR_ARE_DEPENDENT (ddr) == chrec_known || dra == drb) - /* Independent or same data accesses. */ - return false; - - if (DR_IS_READ (dra) == DR_IS_READ (drb) && DR_IS_READ (dra)) - /* Two loads. */ - return false; - - if (vect_print_dump_info (REPORT_DR_DETAILS)) - { - fprintf (vect_dump, "possible store or store/load dependence between "); - print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); - fprintf (vect_dump, " and "); - print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); - } - return true; -} - - /* Function vect_analyze_data_ref_dependences. Examine all the data references in the loop, and make sure there do not @@ -1020,24 +999,12 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) unsigned int i; VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo); struct data_dependence_relation *ddr; - bool check_interleaving = true; if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "=== vect_analyze_dependences ==="); - /* We allow interleaving only if there are no store-store and load-store - dependencies in the loop. */ for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++) - { - if (vect_check_dependences (ddr)) - { - check_interleaving = false; - break; - } - } - - for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++) - if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, check_interleaving)) + if (vect_analyze_data_ref_dependence (ddr, loop_vinfo)) return false; return true; @@ -1778,9 +1745,25 @@ vect_analyze_data_ref_access (struct data_reference *dr) DR_INIT (STMT_VINFO_DATA_REF ( vinfo_for_stmt (next))))) { - /* For load use the same data-ref load. (We check in - vect_check_dependences() that there are no two stores to the - same location). */ + if (!DR_IS_READ (data_ref)) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, "Two store stmts share the same dr."); + return false; + } + + /* Check that there is no load-store dependecies for this loads + to prevent a case of load-store-load to the same location. */ + if (DR_GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (next)) + || DR_GROUP_READ_WRITE_DEPENDENCE (vinfo_for_stmt (prev))) + { + if (vect_print_dump_info (REPORT_DETAILS)) + fprintf (vect_dump, + "READ_WRITE dependence in interleaving."); + return false; + } + + /* For load use the same data-ref load. */ DR_GROUP_SAME_DR_STMT (vinfo_for_stmt (next)) = prev; prev = next; diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 7fb98577951..ee137314dd4 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1373,6 +1373,7 @@ new_stmt_vec_info (tree stmt, loop_vec_info loop_vinfo) DR_GROUP_STORE_COUNT (res) = 0; DR_GROUP_GAP (res) = 0; DR_GROUP_SAME_DR_STMT (res) = NULL_TREE; + DR_GROUP_READ_WRITE_DEPENDENCE (res) = false; return res; } diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index f3234032611..a13ee1e5c69 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -252,6 +252,9 @@ typedef struct _stmt_vec_info { /* In case that two or more stmts share data-ref, this is the pointer to the previously detected stmt with the same dr. */ tree same_dr_stmt; + /* For loads only, if there is a store with the same location, this field is + TRUE. */ + bool read_write_dep; } *stmt_vec_info; /* Access Functions. */ @@ -273,6 +276,7 @@ typedef struct _stmt_vec_info { #define STMT_VINFO_DR_GROUP_STORE_COUNT(S) (S)->store_count #define STMT_VINFO_DR_GROUP_GAP(S) (S)->gap #define STMT_VINFO_DR_GROUP_SAME_DR_STMT(S)(S)->same_dr_stmt +#define STMT_VINFO_DR_GROUP_READ_WRITE_DEPENDENCE(S) (S)->read_write_dep #define DR_GROUP_FIRST_DR(S) (S)->first_dr #define DR_GROUP_NEXT_DR(S) (S)->next_dr @@ -280,6 +284,7 @@ typedef struct _stmt_vec_info { #define DR_GROUP_STORE_COUNT(S) (S)->store_count #define DR_GROUP_GAP(S) (S)->gap #define DR_GROUP_SAME_DR_STMT(S) (S)->same_dr_stmt +#define DR_GROUP_READ_WRITE_DEPENDENCE(S) (S)->read_write_dep #define STMT_VINFO_RELEVANT_P(S) ((S)->relevant != vect_unused_in_loop)