https://gcc.gnu.org/g:2f83ea87ee328d337f87d4430861221be9babe1e

commit r15-1582-g2f83ea87ee328d337f87d4430861221be9babe1e
Author: Richard Biener <rguent...@suse.de>
Date:   Fri Jun 21 13:19:26 2024 +0200

    tree-optimization/115528 - fix vect alignment analysis for outer loop vect
    
    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.
    
            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.

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

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;

Reply via email to