tree-optimization/113371 - avoid prologue peeling for peeled early exits

Message ID 20240116140447.498723858C41@sourceware.org
State Committed
Commit 3359942417b02de88ae84d50aac232ac01ff9e15
Headers
Series tree-optimization/113371 - avoid prologue peeling for peeled early exits |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 success Testing passed

Commit Message

Richard Biener Jan. 16, 2024, 1:59 p.m. UTC
  The following avoids prologue peeling when doing early exit
vectorization with the IV exit before the early exit.  That's because
we it invalidates the invariant that the effective latch of the loop
is empty causing wrong continuation to the main loop.  In particular
this is prone to break virtual SSA form.

Bootstrapped and tested on x86_64-unknown-linux-gnu, will push if
the linaro CI is happy.

Richard.

	PR tree-optimization/113371
	* tree-vect-data-refs.cc (vect_enhance_data_refs_alignment):
	Do not peel when LOOP_VINFO_EARLY_BREAKS_VECT_PEELED.
	* tree-vect-loop-manip.cc (vect_do_peeling): Assert we do
	not perform prologue peeling when LOOP_VINFO_EARLY_BREAKS_VECT_PEELED.

	* gcc.dg/vect/pr113371.c: New testcase.
---
 gcc/testsuite/gcc.dg/vect/pr113371.c | 19 +++++++++++++++++++
 gcc/tree-vect-data-refs.cc           |  5 +++--
 gcc/tree-vect-loop-manip.cc          |  3 ++-
 3 files changed, 24 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr113371.c
  

Patch

diff --git a/gcc/testsuite/gcc.dg/vect/pr113371.c b/gcc/testsuite/gcc.dg/vect/pr113371.c
new file mode 100644
index 00000000000..46c4deb0db9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr113371.c
@@ -0,0 +1,19 @@ 
+/* { dg-do compile } */
+/* { dg-additional-options "-O" } */
+/* { dg-additional-options "-march=silvermont" { target { x86_64-*-* i?86-*-* } } } */
+
+long *BN_uadd_ap;
+
+void
+BN_uadd (int dif, long t1)
+{
+  long *rp;
+  while (dif)
+    {
+      dif--;
+      t1 = *BN_uadd_ap;
+      *rp++ = t1;
+      if (t1)
+        break;
+    }
+}
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 5e86da39468..0495842b350 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -2354,8 +2354,9 @@  vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
   /* Check if we can possibly peel the loop.  */
   if (!vect_can_advance_ivs_p (loop_vinfo)
       || !slpeel_can_duplicate_loop_p (loop, LOOP_VINFO_IV_EXIT (loop_vinfo),
-				       LOOP_VINFO_IV_EXIT (loop_vinfo))
-      || loop->inner)
+				       loop_preheader_edge (loop))
+      || loop->inner
+      || LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo))
     do_peeling = false;
 
   struct _vect_peel_extended_info peel_for_known_alignment;
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index c7e73f65155..8aa9224e1a9 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -3262,7 +3262,8 @@  vect_do_peeling (loop_vec_info loop_vinfo, tree niters, tree nitersm1,
     {
       e = loop_preheader_edge (loop);
       edge exit_e = LOOP_VINFO_IV_EXIT (loop_vinfo);
-      gcc_checking_assert (slpeel_can_duplicate_loop_p (loop, exit_e, e));
+      gcc_checking_assert (slpeel_can_duplicate_loop_p (loop, exit_e, e)
+			   && !LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo));
 
       /* Peel prolog and put it on preheader edge of loop.  */
       edge scalar_e = LOOP_VINFO_SCALAR_IV_EXIT (loop_vinfo);