]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
tree-optimization/114052 - consider infinite sub-loops when lowering iter bound
authorRichard Biener <rguenther@suse.de>
Wed, 29 Jan 2025 12:25:14 +0000 (13:25 +0100)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 30 Jan 2025 09:00:14 +0000 (10:00 +0100)
When we walk stmts to find always executed stmts with UB in the last
iteration to be able to reduce the iteration count by one we fail
to consider infinite subloops in the last iteration that would make
such stmt not execute.  The following adds this.

PR tree-optimization/114052
* tree-ssa-loop-niter.cc (maybe_lower_iteration_bound): Check
for infinite subloops we might not exit.

* gcc.dg/pr114052-1.c: New testcase.

gcc/testsuite/gcc.dg/pr114052-1.c [new file with mode: 0644]
gcc/tree-ssa-loop-niter.cc

diff --git a/gcc/testsuite/gcc.dg/pr114052-1.c b/gcc/testsuite/gcc.dg/pr114052-1.c
new file mode 100644 (file)
index 0000000..98e93bf
--- /dev/null
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-require-effective-target signal } */
+/* { dg-require-effective-target alarm } */
+/* { dg-options "-O2" } */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+volatile int y;
+void __attribute__((noipa)) put(int x)
+{
+  if (y)
+    __builtin_printf ("%i\n", x);
+}
+
+void __attribute__((noipa)) f(void)
+{
+  int counter = 0;
+  while (1) {
+      if (counter >= 2) continue;
+      put (counter++);
+  }
+}
+
+void do_exit (int i)
+{
+  exit (0);
+}
+
+int main()
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = do_exit;
+  s.sa_flags = 0;
+  sigaction (SIGALRM, &s, NULL);
+  alarm (1);
+  f();
+}
index de8d5ae623357945cb419e2d44fdf2f8cc66d46a..7743970bf3d59882d34349b6eb80c4d873d5b9d0 100644 (file)
@@ -4757,7 +4757,14 @@ maybe_lower_iteration_bound (class loop *loop)
           FOR_EACH_EDGE (e, ei, bb->succs)
            {
              if (loop_exit_edge_p (loop, e)
-                 || e == loop_latch_edge (loop))
+                 || e == loop_latch_edge (loop)
+                 /* When exiting an inner loop, verify it is finite.  */
+                 || (!flow_bb_inside_loop_p (bb->loop_father, e->dest)
+                     && !finite_loop_p (bb->loop_father))
+                 /* When we enter an irreducible region and the entry
+                    does not contain a bounding stmt assume it might be
+                    infinite.  */
+                 || (bb->flags & BB_IRREDUCIBLE_LOOP))
                {
                  found_exit = true;
                  break;