When a loop is LOOP_VINFO_EARLY_BREAKS_VECT_PEELED && ! 
LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG
then we still need the epilog loop for the main latch edge.

The early exits themselves when LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG don't need to
go to scalar code.

Allowing bound_epilog to still be set to VF when
LOOP_VINFO_EARLY_BREAKS_VECT_PEELED we get to the desired effect that the early
exits do not require an epilog when !LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG but
the main edge still does if LOOP_VINFO_EARLY_BREAKS_VECT_PEELED.

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Pushed to master.

Thanks,
Tamar

gcc/ChangeLog:

        PR tree-optimization/125804
        * tree-vect-loop-manip.cc (vect_do_peeling): Have
        LOOP_VINFO_EARLY_BREAKS_VECT_PEELED require epilog.

gcc/testsuite/ChangeLog:

        PR tree-optimization/125804
        * gcc.dg/vect/vect-early-break_144-pr125804.c: New test.

-- inline copy of patch --

diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c 
b/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c
new file mode 100644
index 
0000000000000000000000000000000000000000..7afca96e304928042291b56546d7b8a80764dbf4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_144-pr125804.c
@@ -0,0 +1,48 @@
+/* { dg-add-options vect_early_break } */
+/* { dg-do run } */
+/* { dg-require-effective-target vect_early_break_hw } */
+/* { dg-require-effective-target vect_long } */
+
+#include "tree-vect.h"
+
+typedef struct {
+  unsigned b;
+  long long bits[2];
+} c;
+typedef struct {
+  c *d;
+} e, *bitmap;
+e f;
+int g;
+
+__attribute__((noipa))
+int h(bitmap i) {
+  c j = *i->d;
+  unsigned k, l = j.b < 4;
+  for (; l < 2; l++) {
+    long long m = j.bits[l];
+    for (; k < 64; k++) {
+      long long n = (long long)1LL << k;
+      if (m & n)
+        goto o;
+    }
+    k = 0;
+  }
+  return 0;
+o:
+  return 1;
+}
+
+int main() {
+
+  check_vect ();
+
+  c a;
+  a.bits[0] = 1ull << 63;
+  f.d = &a;
+  g = h(&f);
+  return g == 0;
+}
+
+/* { dg-final { scan-tree-dump-times "LOOP VECTORIZED" 1 "vect" } } */
+/* { dg-final { scan-tree-dump "early break does not require epilog" "vect" } 
} */
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 
d2c854e16d4413dc26ab1ec35d20633ef415d01c..a64a79d3299fb65d46c68a438448b7bcd5da0846
 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -3320,7 +3320,8 @@ vect_do_peeling (loop_vec_info loop_vinfo, tree niters, 
tree nitersm1,
   /* For early breaks the scalar loop needs to execute at most VF times
      to find the element that caused the break.  */
   if (LOOP_VINFO_EARLY_BREAKS (loop_vinfo)
-      && LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG (loop_vinfo))
+      && (LOOP_VINFO_EARLY_BRK_NEEDS_EPILOG (loop_vinfo)
+         || LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo)))
     bound_epilog = vf;
 
   bool epilog_peeling = maybe_ne (bound_epilog, 0U);

Attachment: rb20616.patch
Description: rb20616.patch

Reply via email to