OSDN Git Service

2010-04-13 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Apr 2010 09:48:26 +0000 (09:48 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 13 Apr 2010 09:48:26 +0000 (09:48 +0000)
* tree-vect-data-refs.c (vect_analyze_data_ref_dependence):
Only add RW dependence for dependence distance zero.
Adjust maximal vectorization factor according to dependences.
Move alignment handling ...
(vect_find_same_alignment_drs): ... here.  New function.
(vect_analyze_data_ref_dependences): Adjust.
(vect_analyze_data_refs_alignment): Call vect_find_same_alignment_drs.
(vect_analyze_data_refs): Adjust minimal vectorization factor
according to data references.
* tree-vect-loop.c (vect_analyze_loop): Analyze data-ref
dependences before determining the vectorization factor.
Analyze alignment after determining the vectorization factor.
* tree-vect-slp.c ((vect_slp_analyze_bb): Analyze data-ref
dependences before alignment.
* tree-vectorizer.h (vect_analyze_data_ref_dependences):
Adjust prototype.
(vect_analyze_data_refs): Likewise.
(MAX_VECTORIZATION_FACTOR): New define.

* gcc.dg/vect/no-vfa-vect-depend-1.c: Adjust.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158259 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/no-vfa-vect-depend-1.c
gcc/tree-vect-data-refs.c
gcc/tree-vect-loop.c
gcc/tree-vect-slp.c
gcc/tree-vectorizer.h

index 09b704a..32b9987 100644 (file)
@@ -1,3 +1,24 @@
+2010-04-13  Richard Guenther  <rguenther@suse.de>
+
+       * tree-vect-data-refs.c (vect_analyze_data_ref_dependence):
+       Only add RW dependence for dependence distance zero.
+       Adjust maximal vectorization factor according to dependences.
+       Move alignment handling ...
+       (vect_find_same_alignment_drs): ... here.  New function.
+       (vect_analyze_data_ref_dependences): Adjust.
+       (vect_analyze_data_refs_alignment): Call vect_find_same_alignment_drs.
+       (vect_analyze_data_refs): Adjust minimal vectorization factor
+       according to data references.
+       * tree-vect-loop.c (vect_analyze_loop): Analyze data-ref
+       dependences before determining the vectorization factor.
+       Analyze alignment after determining the vectorization factor.
+       * tree-vect-slp.c ((vect_slp_analyze_bb): Analyze data-ref
+       dependences before alignment.
+       * tree-vectorizer.h (vect_analyze_data_ref_dependences):
+       Adjust prototype.
+       (vect_analyze_data_refs): Likewise.
+       (MAX_VECTORIZATION_FACTOR): New define.
+
 2010-04-13  Duncan Sands  <baldrick@free.fr>
 
        * except.h (lang_eh_type_covers): Remove.
index dcce334..55f5e63 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-13  Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/vect/no-vfa-vect-depend-1.c: Adjust.
+
 2010-04-13  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/derived_type1.adb: New test.
index 329478d..5679ff7 100644 (file)
@@ -51,6 +51,6 @@ int main (void)
 }
 
 /* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" {xfail vect_no_align } } } */
-/* { dg-final { scan-tree-dump-times "dependence distance >= VF or negative" 1 "vect"  } } */
+/* { dg-final { scan-tree-dump-times "dependence distance negative" 1 "vect"  } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
 
index a4d6a5f..ba537a0 100644 (file)
@@ -487,21 +487,19 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
 
    Return TRUE if there (might) exist a dependence between a memory-reference
    DRA and a memory-reference DRB.  When versioning for alias may check a
-   dependence at run-time, return FALSE.  */
+   dependence at run-time, return FALSE.  Adjust *MAX_VF according to
+   the data dependence.  */
 
 static bool
 vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
-                                  loop_vec_info loop_vinfo)
+                                  loop_vec_info loop_vinfo, int *max_vf)
 {
   unsigned int i;
   struct loop *loop = NULL;
-  int vectorization_factor = 0;
   struct data_reference *dra = DDR_A (ddr);
   struct data_reference *drb = DDR_B (ddr);
   stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
   stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
-  int dra_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dra))));
-  int drb_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (drb))));
   lambda_vector dist_v;
   unsigned int loop_depth;
 
@@ -513,10 +511,7 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
     }
 
   if (loop_vinfo)
-    {
-      loop = LOOP_VINFO_LOOP (loop_vinfo);
-      vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
-    }
+    loop = LOOP_VINFO_LOOP (loop_vinfo);
 
   if ((DR_IS_READ (dra) && DR_IS_READ (drb) && loop_vinfo) || dra == drb)
     return false;
@@ -595,17 +590,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
       if (vect_print_dump_info (REPORT_DR_DETAILS))
        fprintf (vect_dump, "dependence distance  = %d.", dist);
 
-      /* Same loop iteration.  */
-      if (dist % vectorization_factor == 0 && dra_size == drb_size)
+      if (dist == 0)
        {
-         /* Two references with distance zero have the same alignment.  */
-         VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_a), drb);
-         VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_b), dra);
-         if (vect_print_dump_info (REPORT_ALIGNMENT))
-           fprintf (vect_dump, "accesses have the same alignment.");
          if (vect_print_dump_info (REPORT_DR_DETAILS))
            {
-             fprintf (vect_dump, "dependence distance modulo vf == 0 between ");
+             fprintf (vect_dump, "dependence distance == 0 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);
@@ -621,18 +610,36 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
                 DR_GROUP_READ_WRITE_DEPENDENCE (stmtinfo_b) = true;
            }
 
-          continue;
+         continue;
+       }
+
+      if (dist > 0 && DDR_REVERSED_P (ddr))
+       {
+         /* If DDR_REVERSED_P the order of the data-refs in DDR was
+            reversed (to make distance vector positive), and the actual
+            distance is negative.  */
+         if (vect_print_dump_info (REPORT_DR_DETAILS))
+           fprintf (vect_dump, "dependence distance negative.");
+         continue;
+       }
+
+      if (abs (dist) >= 2
+         && abs (dist) < *max_vf)
+       {
+         /* The dependence distance requires reduction of the maximal
+            vectorization factor.  */
+         *max_vf = abs (dist);
+         if (vect_print_dump_info (REPORT_DR_DETAILS))
+           fprintf (vect_dump, "adjusting maximal vectorization factor to %i",
+                    *max_vf);
        }
 
-      if (abs (dist) >= vectorization_factor
-          || (dist > 0 && DDR_REVERSED_P (ddr)))
+      if (abs (dist) >= *max_vf)
        {
          /* Dependence distance does not create dependence, as far as
-            vectorization is concerned, in this case. If DDR_REVERSED_P the
-            order of the data-refs in DDR was reversed (to make distance
-            vector positive), and the actual distance is negative.  */
+            vectorization is concerned, in this case.  */
          if (vect_print_dump_info (REPORT_DR_DETAILS))
-           fprintf (vect_dump, "dependence distance >= VF or negative.");
+           fprintf (vect_dump, "dependence distance >= VF.");
          continue;
        }
 
@@ -654,11 +661,12 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
 /* Function vect_analyze_data_ref_dependences.
 
    Examine all the data references in the loop, and make sure there do not
-   exist any data dependences between them.  */
+   exist any data dependences between them.  Set *MAX_VF according to
+   the maximum vectorization factor the data dependences allow.  */
 
 bool
 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
-                                   bb_vec_info bb_vinfo)
+                                   bb_vec_info bb_vinfo, int *max_vf)
 {
   unsigned int i;
   VEC (ddr_p, heap) *ddrs = NULL;
@@ -673,7 +681,7 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
     ddrs = BB_VINFO_DDRS (bb_vinfo);
 
   for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
-    if (vect_analyze_data_ref_dependence (ddr, loop_vinfo))
+    if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
       return false;
 
   return true;
@@ -1410,6 +1418,69 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
 }
 
 
+/* Function vect_find_same_alignment_drs.
+
+   Update group and alignment relations according to the chosen
+   vectorization factor.  */
+
+static void
+vect_find_same_alignment_drs (struct data_dependence_relation *ddr,
+                             loop_vec_info loop_vinfo)
+{
+  unsigned int i;
+  struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+  int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+  struct data_reference *dra = DDR_A (ddr);
+  struct data_reference *drb = DDR_B (ddr);
+  stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
+  stmt_vec_info stmtinfo_b = vinfo_for_stmt (DR_STMT (drb));
+  int dra_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dra))));
+  int drb_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (drb))));
+  lambda_vector dist_v;
+  unsigned int loop_depth;
+
+  if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
+    return;
+
+  if ((DR_IS_READ (dra) && DR_IS_READ (drb)) || dra == drb)
+    return;
+
+  if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+    return;
+
+  /* Loop-based vectorization and known data dependence.  */
+  if (DDR_NUM_DIST_VECTS (ddr) == 0)
+    return;
+
+  loop_depth = index_in_loop_nest (loop->num, DDR_LOOP_NEST (ddr));
+  for (i = 0; VEC_iterate (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v); i++)
+    {
+      int dist = dist_v[loop_depth];
+
+      if (vect_print_dump_info (REPORT_DR_DETAILS))
+       fprintf (vect_dump, "dependence distance  = %d.", dist);
+
+      /* Same loop iteration.  */
+      if (dist == 0
+         || (dist % vectorization_factor == 0 && dra_size == drb_size))
+       {
+         /* Two references with distance zero have the same alignment.  */
+         VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_a), drb);
+         VEC_safe_push (dr_p, heap, STMT_VINFO_SAME_ALIGN_REFS (stmtinfo_b), dra);
+         if (vect_print_dump_info (REPORT_ALIGNMENT))
+           fprintf (vect_dump, "accesses have the same alignment.");
+         if (vect_print_dump_info (REPORT_DR_DETAILS))
+           {
+             fprintf (vect_dump, "dependence distance modulo vf == 0 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);
+           }
+       }
+    }
+}
+
+
 /* Function vect_analyze_data_refs_alignment
 
    Analyze the alignment of the data-references in the loop.
@@ -1422,6 +1493,18 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo,
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "=== vect_analyze_data_refs_alignment ===");
 
+  /* Mark groups of data references with same alignment using
+     data dependence information.  */
+  if (loop_vinfo)
+    {
+      VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo);
+      struct data_dependence_relation *ddr;
+      unsigned int i;
+
+      for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
+       vect_find_same_alignment_drs (ddr, loop_vinfo);
+    }
+
   if (!vect_compute_data_refs_alignment (loop_vinfo, bb_vinfo))
     {
       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
@@ -1852,7 +1935,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
 */
 
 bool
-vect_analyze_data_refs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
+vect_analyze_data_refs (loop_vec_info loop_vinfo,
+                       bb_vec_info bb_vinfo,
+                       int *min_vf)
 {
   struct loop *loop = NULL;
   basic_block bb = NULL;
@@ -1907,6 +1992,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
       gimple stmt;
       stmt_vec_info stmt_info;
       tree base, offset, init;
+      int vf;
 
       if (!dr || !DR_REF (dr))
         {
@@ -2079,6 +2165,12 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
             }
           return false;
         }
+
+      /* Adjust the minimal vectorization factor according to the
+        vector type.  */
+      vf = TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info));
+      if (vf > *min_vf)
+       *min_vf = vf;
     }
 
   return true;
index c654795..809f3e1 100644 (file)
@@ -1354,6 +1354,8 @@ vect_analyze_loop (struct loop *loop)
 {
   bool ok;
   loop_vec_info loop_vinfo;
+  int max_vf = MAX_VECTORIZATION_FACTOR;
+  int min_vf = 2;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "===== analyze_loop_nest =====");
@@ -1378,12 +1380,13 @@ vect_analyze_loop (struct loop *loop)
     }
 
   /* Find all data references in the loop (which correspond to vdefs/vuses)
-     and analyze their evolution in the loop.
+     and analyze their evolution in the loop.  Also adjust the minimal
+     vectorization factor according to the loads and stores.
 
      FORNOW: Handle only simple, array references, which
      alignment can be forced, and aligned pointer-references.  */
 
-  ok = vect_analyze_data_refs (loop_vinfo, NULL);
+  ok = vect_analyze_data_refs (loop_vinfo, NULL, &min_vf);
   if (!ok)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
@@ -1410,14 +1413,17 @@ vect_analyze_loop (struct loop *loop)
       return NULL;
     }
 
-  /* Analyze the alignment of the data-refs in the loop.
-     Fail if a data reference is found that cannot be vectorized.  */
+  /* Analyze data dependences between the data-refs in the loop
+     and adjust the maximum vectorization factor according to
+     the dependences.
+     FORNOW: fail at the first data dependence that we encounter.  */
 
-  ok = vect_analyze_data_refs_alignment (loop_vinfo, NULL);
-  if (!ok)
+  ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf);
+  if (!ok
+      || max_vf < min_vf)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "bad data alignment.");
+       fprintf (vect_dump, "bad data dependence.");
       destroy_loop_vec_info (loop_vinfo, true);
       return NULL;
     }
@@ -1430,15 +1436,22 @@ vect_analyze_loop (struct loop *loop)
       destroy_loop_vec_info (loop_vinfo, true);
       return NULL;
     }
+  if (max_vf < LOOP_VINFO_VECT_FACTOR (loop_vinfo))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "bad data dependence.");
+      destroy_loop_vec_info (loop_vinfo, true);
+      return NULL;
+    }
 
-  /* Analyze data dependences between the data-refs in the loop.
-     FORNOW: fail at the first data dependence that we encounter.  */
+  /* Analyze the alignment of the data-refs in the loop.
+     Fail if a data reference is found that cannot be vectorized.  */
 
-  ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL);
+  ok = vect_analyze_data_refs_alignment (loop_vinfo, NULL);
   if (!ok)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "bad data dependence.");
+       fprintf (vect_dump, "bad data alignment.");
       destroy_loop_vec_info (loop_vinfo, true);
       return NULL;
     }
index 0e4f6ce..d25d347 100644 (file)
@@ -1270,6 +1270,8 @@ vect_slp_analyze_bb (basic_block bb)
   slp_instance instance;
   int i, insns = 0;
   gimple_stmt_iterator gsi;
+  int min_vf = 2;
+  int max_vf = MAX_VECTORIZATION_FACTOR;
 
   if (vect_print_dump_info (REPORT_DETAILS))
     fprintf (vect_dump, "===vect_slp_analyze_bb===\n");
@@ -1296,7 +1298,7 @@ vect_slp_analyze_bb (basic_block bb)
   if (!bb_vinfo)
     return NULL;
 
-  if (!vect_analyze_data_refs (NULL, bb_vinfo))
+  if (!vect_analyze_data_refs (NULL, bb_vinfo, &min_vf))
     {
       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
         fprintf (vect_dump, "not vectorized: unhandled data-ref in basic "
@@ -1317,6 +1319,17 @@ vect_slp_analyze_bb (basic_block bb)
       return NULL;
     }
 
+   if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo, &max_vf)
+       || min_vf > max_vf)
+     {
+       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+        fprintf (vect_dump, "not vectorized: unhandled data dependence "
+                 "in basic block.\n");
+
+       destroy_bb_vec_info (bb_vinfo);
+       return NULL;
+     }
+
   if (!vect_analyze_data_refs_alignment (NULL, bb_vinfo))
     {
       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
@@ -1327,16 +1340,6 @@ vect_slp_analyze_bb (basic_block bb)
       return NULL;
     }
 
-   if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo))
-    {
-     if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
-       fprintf (vect_dump, "not vectorized: unhandled data dependence in basic"
-                           " block.\n");
-
-      destroy_bb_vec_info (bb_vinfo);
-      return NULL;
-    }
-
   if (!vect_analyze_data_ref_accesses (NULL, bb_vinfo))
     {
      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
index b46bc52..52b2a7e 100644 (file)
@@ -601,6 +601,9 @@ typedef struct _stmt_vec_info {
    conversion.  */
 #define MAX_INTERM_CVT_STEPS         3
 
+/* The maximum vectorization factor supported by any target (V32QI).  */
+#define MAX_VECTORIZATION_FACTOR 32
+
 /* Avoid GTY(()) on stmt_vec_info.  */
 typedef void *vec_void_p;
 DEF_VEC_P (vec_void_p);
@@ -802,13 +805,14 @@ extern enum dr_alignment_support vect_supportable_dr_alignment
                                            (struct data_reference *);
 extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *,
                                            HOST_WIDE_INT *);
-extern bool vect_analyze_data_ref_dependences (loop_vec_info, bb_vec_info);
+extern bool vect_analyze_data_ref_dependences (loop_vec_info, bb_vec_info,
+                                              int *);
 extern bool vect_enhance_data_refs_alignment (loop_vec_info);
 extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
 extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);
 extern bool vect_analyze_data_ref_accesses (loop_vec_info, bb_vec_info);
 extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
-extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info);
+extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info, int *);
 extern tree vect_create_data_ref_ptr (gimple, struct loop *, tree, tree *,
                                       gimple *, bool, bool *);
 extern tree bump_vector_ptr (tree, gimple, gimple_stmt_iterator *, gimple, tree);