This fixes PR59374, dependence analysis during BB SLP handles cases
that depend on the order of vectorized stmt generation in which case
it ignores WAR dependencies.  But that of course only applies to
references that participate in the vectorization.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Richard.

2013-12-05  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/59374
        * tree-vect-data-refs.c (vect_slp_analyze_data_ref_dependence):
        Commonize known and unknown dependence case fixing the allowed
        read-write dependence case and dropping code that should not
        matter.

        * gcc.dg/torture/pr59374-1.c: New testcase.
        * gcc.dg/torture/pr59374-2.c: Likewise.

Index: gcc/tree-vect-data-refs.c
===================================================================
*** gcc/tree-vect-data-refs.c   (revision 205623)
--- gcc/tree-vect-data-refs.c   (working copy)
*************** vect_slp_analyze_data_ref_dependence (st
*** 497,527 ****
    /* Unknown data dependence.  */
    if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
      {
!       gimple earlier_stmt;
! 
!       if (dump_enabled_p ())
!         {
!           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                            "can't determine dependence between ");
!           dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
!           dump_printf (MSG_MISSED_OPTIMIZATION,  " and ");
!           dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
          dump_printf (MSG_MISSED_OPTIMIZATION,  "\n");
!         }
! 
!       /* We do not vectorize basic blocks with write-write dependencies.  */
!       if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
!         return 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;
      }
! 
!   if (dump_enabled_p ())
      {
        dump_printf_loc (MSG_NOTE, vect_location,
                       "determined dependence between ");
--- 497,513 ----
    /* Unknown data dependence.  */
    if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
      {
!       if  (dump_enabled_p ())
!       {
!         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
!                          "can't determine dependence between ");
!         dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (dra));
!         dump_printf (MSG_MISSED_OPTIMIZATION,  " and ");
!         dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, DR_REF (drb));
          dump_printf (MSG_MISSED_OPTIMIZATION,  "\n");
!       }
      }
!   else if (dump_enabled_p ())
      {
        dump_printf_loc (MSG_NOTE, vect_location,
                       "determined dependence between ");
*************** vect_slp_analyze_data_ref_dependence (st
*** 531,579 ****
        dump_printf (MSG_NOTE,  "\n");
      }
  
!   /* Do not vectorize basic blocks with write-write dependences.  */
    if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
      return true;
  
!   /* Check dependence between DRA and DRB for basic block vectorization.
!      If the accesses share same bases and offsets, we can compare their 
initial
!      constant offsets to decide whether they differ or not.  In case of a 
read-
!      write dependence we check that the load is before the store to ensure 
that
!      vectorization will not change the order of the accesses.  */
! 
!   HOST_WIDE_INT type_size_a, type_size_b, init_a, init_b;
!   gimple earlier_stmt;
! 
!   /* Check that the data-refs have same bases and offsets.  If not, we can't
!      determine if they are dependent.  */
!   if (!operand_equal_p (DR_BASE_ADDRESS (dra), DR_BASE_ADDRESS (drb), 0)
!       || !dr_equal_offsets_p (dra, drb))
!     return true;
! 
!   /* Check the types.  */
!   type_size_a = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dra))));
!   type_size_b = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (drb))));
! 
!   if (type_size_a != type_size_b
!       || !types_compatible_p (TREE_TYPE (DR_REF (dra)),
!                               TREE_TYPE (DR_REF (drb))))
!     return true;
! 
!   init_a = TREE_INT_CST_LOW (DR_INIT (dra));
!   init_b = TREE_INT_CST_LOW (DR_INIT (drb));
! 
!   /* Two different locations - no dependence.  */
!   if (init_a != init_b)
!     return false;
! 
!   /* We have a read-write dependence.  Check that the load is before the 
store.
       When we vectorize basic blocks, vector load can be only before
       corresponding scalar load, and vector store can be only after its
       corresponding scalar store.  So the order of the acceses is preserved in
       case the load is before the store.  */
!   earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
    if (DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
!     return false;
  
    return true;
  }
--- 517,539 ----
        dump_printf (MSG_NOTE,  "\n");
      }
  
!   /* We do not vectorize basic blocks with write-write dependencies.  */
    if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
      return true;
  
!   /* If we have a read-write dependence check that the load is before the 
store.
       When we vectorize basic blocks, vector load can be only before
       corresponding scalar load, and vector store can be only after its
       corresponding scalar store.  So the order of the acceses is preserved in
       case the load is before the store.  */
!   gimple earlier_stmt = get_earlier_stmt (DR_STMT (dra), DR_STMT (drb));
    if (DR_IS_READ (STMT_VINFO_DATA_REF (vinfo_for_stmt (earlier_stmt))))
!     {
!       /* That only holds for load-store pairs taking part in vectorization.  
*/
!       if (STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (dra)))
!         && STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (DR_STMT (drb))))
!       return false;
!     }
  
    return true;
  }
Index: gcc/testsuite/gcc.dg/torture/pr59374-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr59374-1.c    (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr59374-1.c    (working copy)
***************
*** 0 ****
--- 1,24 ----
+ /* { dg-do run } */
+ /* { dg-additional-options "-ftree-slp-vectorize" } */
+ 
+ extern void abort (void);
+ 
+ static struct X { void *a; void *b; } a, b;
+ 
+ void __attribute__((noinline))
+ foo (void)
+ {
+   void *tem = a.b;
+   a.b = (void *)0;
+   b.b = tem;
+   b.a = a.a;
+ }
+ 
+ int main()
+ {
+   a.b = &a;
+   foo ();
+   if (b.b != &a)
+     abort ();
+   return 0;
+ }
Index: gcc/testsuite/gcc.dg/torture/pr59374-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr59374-2.c    (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr59374-2.c    (working copy)
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do run } */
+ /* { dg-additional-options "-ftree-slp-vectorize" } */
+ 
+ extern void abort (void);
+ 
+ static struct X { void *a; void *b; } a, b;
+ static struct X *p;
+ 
+ void __attribute__((noinline))
+ foo (void)
+ {
+   void *tem = a.b;
+   p->b = (void *)0;
+   b.b = tem;
+   b.a = a.a;
+ }
+ 
+ int main()
+ {
+   p = &a;
+   a.b = &a;
+   foo ();
+   if (b.b != &a)
+     abort ();
+   return 0;
+ }

Reply via email to