]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/120927 - 510.parest_r segfault with masked epilog master trunk
authorRichard Biener <rguenther@suse.de>
Thu, 3 Jul 2025 12:39:22 +0000 (14:39 +0200)
committerRichard Biener <rguenther@suse.de>
Fri, 4 Jul 2025 06:34:26 +0000 (08:34 +0200)
The following fixes bad alignment computaton for epilog vectorization
when as in this case for 510.parest_r and masked epilog vectorization
with AVX512 we end up choosing AVX to vectorize the main loop and
masked AVX512 (sic!) to vectorize the epilog.  In that case alignment
analysis for the epilog tries to force alignment of the base to 64,
but that cannot possibly help the epilog when the main loop had used
a vector mode with smaller alignment requirement.

There's another issue, that the check whether the step preserves
alignment needs to consider possibly previously involved VFs
(here, the main loops smaller VF) as well.

These might not be the only case with problems for such a mode mix
but at least there it seems wise to never use DR alignment forcing
when analyzing an epilog.

We get to chose this mode setup because the iteration over epilog
modes doesn't prevent this, the maybe_ge (cached_vf_per_mode[0],
first_vinfo_vf) skip is conditional on !supports_partial_vectors
and it is also conditional on having a cached VF.  Further nothing
in vect_analyze_loop_1 rejects this setup - it might be conceivable
that a target can do masking only for larger modes.  There is a
second reason we end up with this mode setup, which is that
vect_need_peeling_or_partial_vectors_p says we do not need
peeling or partial vectors when analyzing the main loop with
AVX512 (if it would say so we'd have chosen a masked AVX512
epilog-only vectorization).  It does that because it looks at
LOOP_VINFO_COST_MODEL_THRESHOLD (which is not yet computed, so
always zero at this point), and compares max_niter (5) against
the VF (8), but not with equality as the comment says but with
greater.  This also needs looking at, PR120939.

PR tree-optimization/120927
* tree-vect-data-refs.cc (vect_compute_data_ref_alignment):
Do not force a DRs base alignment when analyzing an
epilog loop.  Check whether the step preserves alignment
for all VFs possibly involved sofar.

* gcc.dg/vect/vect-pr120927.c: New testcase.
* gcc.dg/vect/vect-pr120927-2.c: Likewise.

gcc/testsuite/gcc.dg/vect/vect-pr120927-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-pr120927.c [new file with mode: 0644]
gcc/tree-vect-data-refs.cc

diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr120927-2.c b/gcc/testsuite/gcc.dg/vect/vect-pr120927-2.c
new file mode 100644 (file)
index 0000000..e38cebe
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-additional-options "--param vect-partial-vector-usage=1" } */
+/* { dg-additional-options "-mavx512bw -mavx512vl" { target avx512f_runtime } } */
+
+#include "tree-vect.h"
+
+static const double __attribute__((aligned(__BIGGEST_ALIGNMENT__))) a[] = { 1., 2., 3., 4., 5. };
+
+void __attribute__((noipa))
+foo (double *b, double *bp, double c, int n)
+{
+  for (int i = 0; i < n; ++i)
+    b[i] = bp[i] = a[i] * c;
+}
+
+int main()
+{
+  double b[6], bp[6];
+  b[5] = bp[5] = 13.;
+  check_vect ();
+  foo (b, bp, 3., 5);
+  if (b[5] != 13. || bp[5] != 13.)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-pr120927.c b/gcc/testsuite/gcc.dg/vect/vect-pr120927.c
new file mode 100644 (file)
index 0000000..793593f
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-additional-options "--param vect-partial-vector-usage=1" } */
+/* { dg-additional-options "-mavx512bw -mavx512vl" { target avx512f_runtime } } */
+
+#include "tree-vect.h"
+
+static const double a[] = { 1., 2., 3., 4., 5. };
+
+void __attribute__((noipa))
+foo (double *b, double *bp, double c, int n)
+{
+  for (int i = 0; i < n; ++i)
+    b[i] = bp[i] = a[i] * c;
+}
+
+int main()
+{
+  double b[6], bp[6];
+  b[5] = bp[5] = 13.;
+  check_vect ();
+  foo (b, bp, 3., 5);
+  if (b[5] != 13. || bp[5] != 13.)
+    abort ();
+  return 0;
+}
index ee040eb98881dabeb3f297a790d3ec97e5ede452..c84cd29116edf2a48f7c8b5cd40debd7fbeab922 100644 (file)
@@ -1501,10 +1501,17 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
       /* 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 (drb->step_alignment * vf, vect_align_c);
+        the dataref evenly divides by the alignment.  Make sure to check
+        previous epilogues and the main loop.  */
+      step_preserves_misalignment_p = true;
+      auto lvinfo = loop_vinfo;
+      while (lvinfo)
+       {
+         poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (lvinfo);
+         step_preserves_misalignment_p
+           &= multiple_p (drb->step_alignment * vf, vect_align_c);
+         lvinfo = LOOP_VINFO_ORIG_LOOP_INFO (lvinfo);
+       }
 
       if (!step_preserves_misalignment_p && dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -1571,6 +1578,7 @@ vect_compute_data_ref_alignment (vec_info *vinfo, dr_vec_info *dr_info,
       unsigned int max_alignment;
       tree base = get_base_for_alignment (drb->base_address, &max_alignment);
       if (max_alignment < vect_align_c
+         || (loop_vinfo && LOOP_VINFO_EPILOGUE_P (loop_vinfo))
          || !vect_can_force_dr_alignment_p (base,
                                             vect_align_c * BITS_PER_UNIT))
        {