diff mbox

SLP data dependence testing - PR 50819

Message ID CAKSNEw4LdShxU=ftMS9s2TSGSPp2wOn9V9SWffqhwuNFM35svA@mail.gmail.com
State New
Headers show

Commit Message

Ira Rosen Oct. 23, 2011, 12:16 p.m. UTC
Hi,

When there is pair of data-refs with unknown dependence in basic block
SLP we currently require all the loads in the basic block to be before
all the stores in order to avoid load after store dependencies. But
this is too conservative. It's enough to check that in the pairs of
loads and stores with unknown and known dependence, the load comes
first. This is already done for the known case. This patch adds such
check for unknown dependencies and removes
vect_bb_vectorizable_with_dependencies.

Bootstrapped and tested on powerpc64-suse-linux.
Committed.

Ira

ChangeLog:

        PR tree-optimization/50819
        * tree-vectorizer.h (vect_analyze_data_ref_dependences): Remove
        the last argument.
        * tree-vect-loop.c (vect_analyze_loop_2): Update call to
        vect_analyze_data_ref_dependences.
        * tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Remove
        the last argument.  Check load-after-store dependence for unknown
        dependencies in basic blocks.
        (vect_analyze_data_ref_dependences): Update call to
        vect_analyze_data_ref_dependences.
        * tree-vect-patterns.c (vect_recog_widen_shift_pattern): Fix typo.
        * tree-vect-slp.c (vect_bb_vectorizable_with_dependencies): Remove.
        (vect_slp_analyze_bb_1): Update call to
        vect_analyze_data_ref_dependences.  Don't call
        vect_bb_vectorizable_with_dependencies.

testsuite/Changelog:

        PR tree-optimization/50819
        * g++.dg/vect/vect.exp: Set target dependent flags for slp-* tests.
        * g++.dg/vect/slp-pr50819.cc: New test.
diff mbox

Patch

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 180333)
+++ ChangeLog	(working copy)
@@ -1,3 +1,21 @@ 
+2011-10-23  Ira Rosen  <ira.rosen@linaro.org>
+
+	PR tree-optimization/50819
+	* tree-vectorizer.h (vect_analyze_data_ref_dependences): Remove
+	the last argument.
+	* tree-vect-loop.c (vect_analyze_loop_2): Update call to
+	vect_analyze_data_ref_dependences.
+	* tree-vect-data-refs.c (vect_analyze_data_ref_dependence): Remove
+	the last argument.  Check load-after-store dependence for unknown
+	dependencies in basic blocks.
+	(vect_analyze_data_ref_dependences): Update call to
+	vect_analyze_data_ref_dependences.
+	* tree-vect-patterns.c (vect_recog_widen_shift_pattern): Fix typo.
+	* tree-vect-slp.c (vect_bb_vectorizable_with_dependencies): Remove.
+	(vect_slp_analyze_bb_1): Update call to
+	vect_analyze_data_ref_dependences.  Don't call
+	vect_bb_vectorizable_with_dependencies.
+
 2011-10-22  David S. Miller  <davem@davemloft.net>
 
 	* config/sparc/sparc.h (SECONDARY_INPUT_RELOAD_CLASS,
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 180333)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,9 @@ 
+2011-10-23  Ira Rosen  <ira.rosen@linaro.org>
+
+	PR tree-optimization/50819
+	* g++.dg/vect/vect.exp: Set target dependent flags for slp-* tests.
+	* g++.dg/vect/slp-pr50819.cc: New test.
+
 2011-10-21  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/45385
Index: testsuite/g++.dg/vect/vect.exp
===================================================================
--- testsuite/g++.dg/vect/vect.exp	(revision 180333)
+++ testsuite/g++.dg/vect/vect.exp	(working copy)
@@ -42,12 +42,6 @@  set DEFAULT_VECTCFLAGS ""
 # These flags are used for all targets.
 lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fno-vect-cost-model"
 
-set VECT_SLP_CFLAGS $DEFAULT_VECTCFLAGS
-
-lappend DEFAULT_VECTCFLAGS "-fdump-tree-vect-details"
-lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
-
-
 # Skip these tests for targets that do not support generating vector
 # code.  Set additional target-dependent vector flags, which can be
 # overridden by using dg-options in individual tests.
@@ -55,6 +49,11 @@  if ![check_vect_support_and_set_flags] {
     return
 }
 
+set VECT_SLP_CFLAGS $DEFAULT_VECTCFLAGS
+
+lappend DEFAULT_VECTCFLAGS "-fdump-tree-vect-details"
+lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
+
 # Initialize `dg'.
 dg-init
 
Index: testsuite/g++.dg/vect/slp-pr50819.cc
===================================================================
--- testsuite/g++.dg/vect/slp-pr50819.cc	(revision 0)
+++ testsuite/g++.dg/vect/slp-pr50819.cc	(revision 0)
@@ -0,0 +1,53 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+
+typedef float Value;
+
+struct LorentzVector
+{
+
+  LorentzVector(Value x=0, Value  y=0, Value  z=0, Value  t=0) :
+theX(x),theY(y),theZ(z),theT(t){}
+  LorentzVector & operator+=(const LorentzVector & a) {
+    theX += a.theX;
+    theY += a.theY;
+    theZ += a.theZ;
+    theT += a.theT;
+    return *this;
+  }
+
+  Value theX;
+  Value theY;
+  Value theZ;
+  Value theT;
+}  __attribute__ ((aligned(16)));
+
+inline LorentzVector
+operator+(LorentzVector const & a, LorentzVector const & b) {
+  return
+LorentzVector(a.theX+b.theX,a.theY+b.theY,a.theZ+b.theZ,a.theT+b.theT);
+}
+
+inline LorentzVector
+operator*(LorentzVector const & a, Value s) {
+    return LorentzVector(a.theX*s,a.theY*s,a.theZ*s,a.theT*s);
+}
+
+inline LorentzVector
+operator*(Value s, LorentzVector const & a) {
+  return a*s;
+}
+
+
+void sum1(LorentzVector & res, Value s, LorentzVector const & v1, LorentzVector
+const & v2) {
+  res += s*(v1+v2);
+}
+
+void sum2(LorentzVector & res, Value s, LorentzVector const & v1, LorentzVector
+const & v2) {
+  res = res + s*(v1+v2);
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 2 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
Index: tree-vectorizer.h
===================================================================
--- tree-vectorizer.h	(revision 180333)
+++ tree-vectorizer.h	(working copy)
@@ -832,7 +832,7 @@  extern enum dr_alignment_support vect_supportable_
 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,
-					       int *, bool *);
+					       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);
Index: tree-vect-loop.c
===================================================================
--- tree-vect-loop.c	(revision 180333)
+++ tree-vect-loop.c	(working copy)
@@ -1473,7 +1473,7 @@  vect_analyze_loop_operations (loop_vec_info loop_v
 static bool
 vect_analyze_loop_2 (loop_vec_info loop_vinfo)
 {
-  bool ok, dummy, slp = false;
+  bool ok, slp = false;
   int max_vf = MAX_VECTORIZATION_FACTOR;
   int min_vf = 2;
 
@@ -1514,7 +1514,7 @@  vect_analyze_loop_2 (loop_vec_info loop_vinfo)
      the dependences.
      FORNOW: fail at the first data dependence that we encounter.  */
 
-  ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf, &dummy);
+  ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL, &max_vf);
   if (!ok
       || max_vf < min_vf)
     {
Index: tree-vect-data-refs.c
===================================================================
--- tree-vect-data-refs.c	(revision 180333)
+++ tree-vect-data-refs.c	(working copy)
@@ -555,8 +555,7 @@  vect_mark_for_runtime_alias_test (ddr_p ddr, loop_
 
 static bool
 vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
-                                  loop_vec_info loop_vinfo, int *max_vf,
-                                  bool *data_dependence_in_bb)
+                                  loop_vec_info loop_vinfo, int *max_vf)
 {
   unsigned int i;
   struct loop *loop = NULL;
@@ -587,6 +586,8 @@  vect_analyze_data_ref_dependence (struct data_depe
 
   if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
     {
+      gimple earlier_stmt;
+
       if (loop_vinfo)
         {
           if (vect_print_dump_info (REPORT_DR_DETAILS))
@@ -624,10 +625,11 @@  vect_analyze_data_ref_dependence (struct data_depe
       if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
         return true;
 
-      /* We deal with read-write dependencies in basic blocks later (by
-         verifying that all the loads in the basic block are before all the
-         stores).  */
-      *data_dependence_in_bb = true;
+      /* Check that it's not a load-after-store dependence.  */
+      earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
+      if (DR_IS_WRITE (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
+        return true;
+
       return false;
     }
 
@@ -753,8 +755,7 @@  vect_analyze_data_ref_dependence (struct data_depe
 
 bool
 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
-                                   bb_vec_info bb_vinfo, int *max_vf,
-                                   bool *data_dependence_in_bb)
+                                   bb_vec_info bb_vinfo, int *max_vf)
 {
   unsigned int i;
   VEC (ddr_p, heap) *ddrs = NULL;
@@ -769,8 +770,7 @@  vect_analyze_data_ref_dependences (loop_vec_info l
     ddrs = BB_VINFO_DDRS (bb_vinfo);
 
   FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
-    if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf,
-					  data_dependence_in_bb))
+    if (vect_analyze_data_ref_dependence (ddr, loop_vinfo, max_vf))
       return false;
 
   return true;
Index: tree-vect-patterns.c
===================================================================
--- tree-vect-patterns.c	(revision 180333)
+++ tree-vect-patterns.c	(working copy)
@@ -1225,7 +1225,7 @@  vect_recog_over_widening_pattern (VEC (gimple, hea
 
   where type 'TYPE' is at least double the size of type 'type'.
 
-  Also detect unsgigned cases:
+  Also detect unsigned cases:
 
   unsigned type a_t;
   unsigned TYPE u_res_T;
Index: tree-vect-slp.c
===================================================================
--- tree-vect-slp.c	(revision 180333)
+++ tree-vect-slp.c	(working copy)
@@ -1706,43 +1706,6 @@  vect_slp_analyze_operations (bb_vec_info bb_vinfo)
   return true;
 }
 
-/* Check if loads and stores are mixed in the basic block (in that
-   case if we are not sure that the accesses differ, we can't vectorize the
-   basic block).  Also return FALSE in case that there is statement marked as
-   not vectorizable.  */
-
-static bool
-vect_bb_vectorizable_with_dependencies (bb_vec_info bb_vinfo)
-{
-  basic_block bb = BB_VINFO_BB (bb_vinfo);
-  gimple_stmt_iterator si;
-  bool detected_store = false;
-  gimple stmt;
-  struct data_reference *dr;
-
-  for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
-    {
-      stmt = gsi_stmt (si);
-
-      /* We can't allow not analyzed statements, since they may contain data
-         accesses.  */ 
-      if (!STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (stmt)))
-        return false;
-
-      if (!STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt)))
-        continue;
-
-      dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt));
-      if (DR_IS_READ (dr) && detected_store)
-        return false;
-
-      if (!DR_IS_READ (dr))
-        detected_store = true;
-    }
-
-  return true;
-}
-
 /* Check if vectorization of the basic block is profitable.  */
 
 static bool
@@ -1823,7 +1786,6 @@  vect_slp_analyze_bb_1 (basic_block bb)
   int i;
   int min_vf = 2;
   int max_vf = MAX_VECTORIZATION_FACTOR;
-  bool data_dependence_in_bb = false;
 
   bb_vinfo = new_bb_vec_info (bb);
   if (!bb_vinfo)
@@ -1850,11 +1812,8 @@  vect_slp_analyze_bb_1 (basic_block bb)
       return NULL;
     }
 
-   if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo, &max_vf, 
-                                           &data_dependence_in_bb)
-       || min_vf > max_vf
-       || (data_dependence_in_bb 
-           && !vect_bb_vectorizable_with_dependencies (bb_vinfo)))
+   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 "