re PR tree-optimization/78185 (Wrong branch optimization with -O1 on x86/x86_64)
authorRichard Biener <rguenther@suse.de>
Fri, 4 Nov 2016 08:54:42 +0000 (08:54 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 4 Nov 2016 08:54:42 +0000 (08:54 +0000)
2016-11-04  Richard Biener  <rguenther@suse.de>

PR middle-end/78185
* loop-invariant.c (find_exits): Record entering inner
loops as possibly exiting to handle infinite sub-loops.
* tree-ssa-loop-im.c: Include tree-ssa-loop-niter.h.
(fill_always_executed_in_1): Honor infinite child loops.

* gcc.dg/pr78185.c: New testcase.

From-SVN: r241841

gcc/ChangeLog
gcc/loop-invariant.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr78185.c [new file with mode: 0644]
gcc/tree-ssa-loop-im.c

index 9222baaa498387de6ecbfe4c1cd23a6ef906e153..8a455c1e1ef9cfb842762e5fa39b95a9f96ed42b 100644 (file)
@@ -1,3 +1,11 @@
+2016-11-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/78185
+       * loop-invariant.c (find_exits): Record entering inner
+       loops as possibly exiting to handle infinite sub-loops.
+       * tree-ssa-loop-im.c: Include tree-ssa-loop-niter.h.
+       (fill_always_executed_in_1): Honor infinite child loops.
+
 2016-11-03  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        PR target/78192
index 551103fcf4698cd66709b309fe50b6a9a38efcb6..f617241ef0fc467db19e21c6fce8e7300ac1817b 100644 (file)
@@ -598,13 +598,17 @@ find_exits (struct loop *loop, basic_block *body,
 
          FOR_EACH_EDGE (e, ei, body[i]->succs)
            {
-             if (flow_bb_inside_loop_p (loop, e->dest))
-               continue;
-
-             bitmap_set_bit (may_exit, i);
-             bitmap_set_bit (has_exit, i);
-             outermost_exit = find_common_loop (outermost_exit,
-                                                e->dest->loop_father);
+             if (! flow_bb_inside_loop_p (loop, e->dest))
+               {
+                 bitmap_set_bit (may_exit, i);
+                 bitmap_set_bit (has_exit, i);
+                 outermost_exit = find_common_loop (outermost_exit,
+                                                    e->dest->loop_father);
+               }
+             /* If we enter a subloop that might never terminate treat
+                it like a possible exit.  */
+             if (flow_loop_nested_p (loop, e->dest->loop_father))
+               bitmap_set_bit (may_exit, i);
            }
          continue;
        }
index c62bb935966003a35453b18d54f5292ec083245c..9451ca975cfcb413b887c04ccd0005954a3cc622 100644 (file)
@@ -1,3 +1,8 @@
+2016-11-04  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/78185
+       * gcc.dg/pr78185.c: New testcase.
+
 2016-10-04  David Edelsohn  <dje.gcc@gmail.com>
 
        * g++.dg/debug/dwarf2/ref-3.C: XFAIL AIX.
diff --git a/gcc/testsuite/gcc.dg/pr78185.c b/gcc/testsuite/gcc.dg/pr78185.c
new file mode 100644 (file)
index 0000000..405f748
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O" } */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static char var1 = 0L;
+static char *var2 = &var1;
+
+void do_exit (int i)
+{
+  exit (0);
+}
+
+int main(void)
+{
+  struct sigaction s;
+  sigemptyset (&s.sa_mask);
+  s.sa_handler = do_exit;
+  s.sa_flags = 0;
+  sigaction (SIGALRM, &s, NULL);
+  alarm (1);
+  /* The following loop is infinite, the division by zero should not
+     be hoisted out of it.  */
+  for (; (var1 == 0 ? 0 : (100 / var1)) == *var2; );
+  return 0;
+}
index 463db048cb6468da476ba0e499bb31c0a6384c30..0524e57564f8ddeb7555be1fab15045cc3473ea7 100644 (file)
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "trans-mem.h"
 #include "gimple-fold.h"
 #include "tree-scalar-evolution.h"
+#include "tree-ssa-loop-niter.h"
 
 /* TODO:  Support for predicated code motion.  I.e.
 
@@ -2369,8 +2370,16 @@ fill_always_executed_in_1 (struct loop *loop, sbitmap contains_call)
            break;
 
          FOR_EACH_EDGE (e, ei, bb->succs)
-           if (!flow_bb_inside_loop_p (loop, e->dest))
-             break;
+           {
+             /* If there is an exit from this BB.  */
+             if (!flow_bb_inside_loop_p (loop, e->dest))
+               break;
+             /* Or we enter a possibly non-finite loop.  */
+             if (flow_loop_nested_p (bb->loop_father,
+                                     e->dest->loop_father)
+                 && ! finite_loop_p (e->dest->loop_father))
+               break;
+           }
          if (e)
            break;