tree-vectorizer.h (struct _stmt_vec_info): Add new field read_write_dep and macros...
authorIra Rosen <irar@il.ibm.com>
Sun, 21 Jan 2007 09:22:56 +0000 (09:22 +0000)
committerIra Rosen <irar@gcc.gnu.org>
Sun, 21 Jan 2007 09:22:56 +0000 (09:22 +0000)
* 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.

From-SVN: r121026

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-strided-same-dr.c [new file with mode: 0644]
gcc/tree-vect-analyze.c
gcc/tree-vectorizer.c
gcc/tree-vectorizer.h

index 62680ca..de07527 100644 (file)
@@ -1,3 +1,19 @@
+2007-01-21  Ira Rosen  <irar@il.ibm.com>
+
+       * 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  <roger@eyesopen.com>
            Joseph Myers  <joseph@codesourcery.com>
 
index 320c902..d248286 100644 (file)
@@ -1,3 +1,7 @@
+2007-01-21  Ira Rosen  <irar@il.ibm.com> 
+
+       * gcc.dg/vect/vect-strided-same-dr.c: New test. 
+
 2007-01-20  Andrew Pinski  <pinskia@gmail.com>
 
        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 (file)
index 0000000..f04658d
--- /dev/null
@@ -0,0 +1,77 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#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" } } */
+  
index 114f823..c53c34e 100644 (file)
@@ -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;
index 7fb9857..ee13731 100644 (file)
@@ -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;
 }
index f323403..a13ee1e 100644 (file)
@@ -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)