For outer loop vectorization of a data reference in the inner loop
we have to look at both steps to see if they preserve alignment.

What is special for this testcase is that the outer loop step is
one element but the inner loop step four and that we now use SLP
and the vectorization factor is one.  But the issue looks latent
to me.

Bootstrapped on x86_64-unknown-linux-gnu, testing in progress.

        PR tree-optimization/115528
        * tree-vect-data-refs.cc (vect_compute_data_ref_alignment):
        Make sure to look at both the inner and outer loop step
        behavior.

        * gfortran.dg/vect/pr115528.f: New testcase.
---
 gcc/testsuite/gfortran.dg/vect/pr115528.f | 27 +++++++++++
 gcc/tree-vect-data-refs.cc                | 57 ++++++++++++-----------
 2 files changed, 56 insertions(+), 28 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/vect/pr115528.f

diff --git a/gcc/testsuite/gfortran.dg/vect/pr115528.f 
b/gcc/testsuite/gfortran.dg/vect/pr115528.f
new file mode 100644
index 00000000000..764a4b92b3e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/vect/pr115528.f
@@ -0,0 +1,27 @@
+! { dg-additional-options "-fno-inline" }
+
+      subroutine init(COEF1,FORM1,AA)
+      double precision COEF1,X
+      double complex FORM1
+      double precision AA(4,4)
+      COEF1=0
+      FORM1=0
+      AA=0
+      end
+      subroutine curr(HADCUR)
+      double precision COEF1
+      double complex HADCUR(4),FORM1
+      double precision AA(4,4)
+      call init(COEF1,FORM1,AA)
+      do i = 1,4
+         do j = 1,4
+            HADCUR(I)=
+     $         HADCUR(I)+CMPLX(COEF1)*FORM1*AA(I,J)
+         end do
+      end do
+      end
+      program test
+        double complex HADCUR(4)
+        hadcur=0
+        call curr(hadcur)
+      end
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index ae237407672..959e127c385 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -1356,42 +1356,43 @@ vect_compute_data_ref_alignment (vec_info *vinfo, 
dr_vec_info *dr_info,
       step_preserves_misalignment_p = true;
     }
 
-  /* In case the dataref is in an inner-loop of the loop that is being
-     vectorized (LOOP), we use the base and misalignment information
-     relative to the outer-loop (LOOP).  This is ok only if the misalignment
-     stays the same throughout the execution of the inner-loop, which is why
-     we have to check that the stride of the dataref in the inner-loop evenly
-     divides by the vector alignment.  */
-  else if (nested_in_vect_loop_p (loop, stmt_info))
-    {
-      step_preserves_misalignment_p
-       = (DR_STEP_ALIGNMENT (dr_info->dr) % vect_align_c) == 0;
-
-      if (dump_enabled_p ())
-       {
-         if (step_preserves_misalignment_p)
-           dump_printf_loc (MSG_NOTE, vect_location,
-                            "inner step divides the vector alignment.\n");
-         else
-           dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                            "inner step doesn't divide the vector"
-                            " alignment.\n");
-       }
-    }
-
-  /* Similarly we can only use base and misalignment information relative to
-     an innermost loop if the misalignment stays the same throughout the
-     execution of the loop.  As above, this is the case if the stride of
-     the dataref evenly divides by the alignment.  */
   else
     {
+      /* We can only use base and misalignment information relative to
+        an innermost loop if the misalignment stays the same throughout the
+        execution of the loop.  As above, this is the case if the stride of
+        the dataref evenly divides by the alignment.  */
       poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
       step_preserves_misalignment_p
-       = multiple_p (DR_STEP_ALIGNMENT (dr_info->dr) * vf, vect_align_c);
+       = multiple_p (drb->step_alignment * vf, vect_align_c);
 
       if (!step_preserves_misalignment_p && dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
                         "step doesn't divide the vector alignment.\n");
+
+      /* In case the dataref is in an inner-loop of the loop that is being
+        vectorized (LOOP), we use the base and misalignment information
+        relative to the outer-loop (LOOP).  This is ok only if the
+        misalignment stays the same throughout the execution of the
+        inner-loop, which is why we have to check that the stride of the
+        dataref in the inner-loop evenly divides by the vector alignment.  */
+      if (step_preserves_misalignment_p
+         && nested_in_vect_loop_p (loop, stmt_info))
+       {
+         step_preserves_misalignment_p
+           = (DR_STEP_ALIGNMENT (dr_info->dr) % vect_align_c) == 0;
+
+         if (dump_enabled_p ())
+           {
+             if (step_preserves_misalignment_p)
+               dump_printf_loc (MSG_NOTE, vect_location,
+                                "inner step divides the vector alignment.\n");
+             else
+               dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                                "inner step doesn't divide the vector"
+                                " alignment.\n");
+           }
+       }
     }
 
   unsigned int base_alignment = drb->base_alignment;
-- 
2.35.3

Reply via email to