The following fixes PR68379.

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

Richard.

2015-11-30  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/68379
        * tree-vect-stmts.c (vectorizable_load): For BB vectorization
        always base loads on the first used DR of a group.
        * tree-vect-data-refs.c (vect_slp_analyze_and_verify_node_alignment):
        Compute alignment of the first scalar element unconditionally.

        * gcc.dg/torture/pr68379.c: New testcase.
        * gfortran.dg/pr68379-1.f90: Likewise.
        * gfortran.dg/pr68379-2.f: Likewise.

Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c       (revision 231065)
+++ gcc/tree-vect-stmts.c       (working copy)
@@ -6130,6 +6133,7 @@ vectorizable_load (gimple *stmt, gimple_
   bool grouped_load = false;
   bool load_lanes_p = false;
   gimple *first_stmt;
+  gimple *first_stmt_for_drptr = NULL;
   bool inv_p;
   bool negative = false;
   bool compute_in_loop = false;
@@ -6733,10 +6737,14 @@ vectorizable_load (gimple *stmt, gimple_
   if (grouped_load)
     {
       first_stmt = GROUP_FIRST_ELEMENT (stmt_info);
-      /* For BB vectorization we directly vectorize a subchain
+      /* For SLP vectorization we directly vectorize a subchain
          without permutation.  */
       if (slp && ! SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
-        first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+       first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
+      /* For BB vectorization always use the first stmt to base
+        the data ref pointer on.  */
+      if (bb_vinfo)
+       first_stmt_for_drptr = SLP_TREE_SCALAR_STMTS (slp_node)[0];
 
       /* Check if the chain of loads is already vectorized.  */
       if (STMT_VINFO_VEC_STMT (vinfo_for_stmt (first_stmt))
@@ -6948,6 +6956,24 @@ vectorizable_load (gimple *stmt, gimple_
                                              (DR_REF (first_dr)), 0);
              inv_p = false;
            }
+         else if (first_stmt_for_drptr
+                  && first_stmt != first_stmt_for_drptr)
+           {
+             dataref_ptr
+               = vect_create_data_ref_ptr (first_stmt_for_drptr, aggr_type,
+                                           at_loop, offset, &dummy, gsi,
+                                           &ptr_incr, simd_lane_access_p,
+                                           &inv_p, byte_offset);
+             /* Adjust the pointer by the difference to first_stmt.  */
+             data_reference_p ptrdr
+               = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt_for_drptr));
+             tree diff = fold_convert (sizetype,
+                                       size_binop (MINUS_EXPR,
+                                                   DR_INIT (first_dr),
+                                                   DR_INIT (ptrdr)));
+             dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
+                                            stmt, diff);
+           }
          else
            dataref_ptr
              = vect_create_data_ref_ptr (first_stmt, aggr_type, at_loop,
Index: gcc/testsuite/gcc.dg/torture/pr68379.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr68379.c      (revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr68379.c      (working copy)
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+int a, b[3], c[3][5];
+
+void
+fn1 ()
+{
+  int e;
+  for (a = 2; a >= 0; a--)
+    for (e = 0; e < 4; e++)
+      c[a][e] = b[a];
+}
Index: gcc/testsuite/gfortran.dg/pr68379-1.f90
===================================================================
--- gcc/testsuite/gfortran.dg/pr68379-1.f90     (revision 0)
+++ gcc/testsuite/gfortran.dg/pr68379-1.f90     (working copy)
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! { dg-options "-O3" }
+MODULE qs_efield_berry
+  TYPE cp_error_type
+  END TYPE
+  INTEGER, PARAMETER :: dp=8
+  TYPE qs_energy_type
+    REAL(KIND=dp), POINTER :: efield
+  END TYPE
+  TYPE qs_environment_type
+  END TYPE
+  INTERFACE 
+    SUBROUTINE foo(qs_env,energy,error)
+       IMPORT 
+       TYPE(qs_environment_type), POINTER :: qs_env
+       TYPE(cp_error_type)      :: error
+       TYPE(qs_energy_type), POINTER   :: energy
+    END SUBROUTINE
+  END INTERFACE
+CONTAINS
+  SUBROUTINE qs_efield_mo_derivatives()
+    TYPE(qs_environment_type), POINTER :: qs_env
+    TYPE(cp_error_type)  :: error
+    COMPLEX(dp)          ::   zi(3), zphase(3)
+    REAL(dp)             :: ci(3)
+    TYPE(qs_energy_type), POINTER      :: energy
+    CALL foo(qs_env, energy, error)
+    zi = zi * zphase
+    ci = AIMAG(LOG(zi))
+    DO idir=1,3
+       ener_field=ener_field+ci(idir)*fieldfac(idir)
+    END DO
+    energy%efield=ener_field
+  END SUBROUTINE qs_efield_mo_derivatives
+END MODULE qs_efield_berry
Index: gcc/testsuite/gfortran.dg/pr68379-2.f
===================================================================
--- gcc/testsuite/gfortran.dg/pr68379-2.f       (revision 0)
+++ gcc/testsuite/gfortran.dg/pr68379-2.f       (working copy)
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-additional-options "-Ofast" }
+! { dg-additional-options "-mavx" { target x86_64-*-* i?86-*-* } }
+
+      SUBROUTINE PASSB4 (IDO,L1,CC,CH,WA1,WA2,WA3)
+      IMPLICIT REAL(4) (A-H, O-Z)
+      DIMENSION CC(IDO,4,L1), CH(IDO,L1,4), WA1(*), WA2(*), WA3(*)
+  102 DO 104 K=1,L1
+         DO 103 I=2,IDO,2
+            TI1 = CC(I,1,K)-CC(I,3,K)
+            TI2 = CC(I,1,K)+CC(I,3,K)
+            TI3 = CC(I,2,K)+CC(I,4,K)
+            TR2 = CC(I-1,1,K)+CC(I-1,3,K)
+            TI4 = CC(I-1,2,K)-CC(I-1,4,K)
+            TR3 = CC(I-1,2,K)+CC(I-1,4,K)
+            CH(I-1,K,1) = TR2+TR3
+            CH(I,K,1) = TI2+TI3
+            CI4 = TI1-TI4
+            CH(I-1,K,4) = CI4
+            CH(I,K,4) = CI4
+  103    CONTINUE
+  104 CONTINUE
+      RETURN
+      END
Index: gcc/tree-vect-data-refs.c
===================================================================
--- gcc/tree-vect-data-refs.c   (revision 231101)
+++ gcc/tree-vect-data-refs.c   (working copy)
@@ -2102,11 +2102,16 @@ vect_slp_analyze_and_verify_node_alignme
      the node is permuted in which case we start from the first
      element in the group.  */
   gimple *first_stmt = SLP_TREE_SCALAR_STMTS (node)[0];
+  data_reference_p first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt 
(first_stmt));
   if (SLP_TREE_LOAD_PERMUTATION (node).exists ())
     first_stmt = GROUP_FIRST_ELEMENT (vinfo_for_stmt (first_stmt));
 
   data_reference_p dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
   if (! vect_compute_data_ref_alignment (dr)
+      /* For creating the data-ref pointer we need alignment of the
+        first element anyway.  */
+      || (dr != first_dr
+         && ! vect_compute_data_ref_alignment (first_dr))
       || ! verify_data_ref_alignment (dr))
     {
       if (dump_enabled_p ())

Reply via email to