On Wed, 2 Nov 2016, Richard Biener wrote:

> 
> The following fixes PR78185 by properly honoring possibly infinite child
> loops when computing what blocks are always executed during loop invariant
> motion.  Such loops behave as if the loop would exit at this point.
> 
> Both GIMPLE and RTL level passes have that very same issue and the 
> following fixes the GIMPLE one and simply disables hoisting of possibly
> trapping or faulting instructions in the RTL pass ... Eric seems to
> remember this might regress gzip so I'm going to put this on one of
> our SPEC testers for tonights run as well.  Maybe somebody else

Nothing popped out, but ...

> wants to check the performance impact (I'm interested in both,
> GIMPLE and RTL change fallout for performance).
> 
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
> 
> If all goes well I'll followup with the obvious removal of no longer
> needed stuff in loop-invariant.c.
> 
> Another variant for RTL would be to simply treat all edges entering
> a child loop (not only those entering possibly infinitely looping ones)
> as an exit.  I think finite_loop_p has no RTL level variant (yet).

... that was easy enough to implement and should be slightly less
conservative.

Re-bootstrap / regtest running on x86_64-unknown-linux-gnu.  I'll
commit that if nobody objects until tomorrow.

Richard.

2016-11-03  Richard Biener  <rguent...@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.

Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c      (revision 241795)
+++ gcc/tree-ssa-loop-im.c      (working copy)
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3.
 #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 *
            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;
 
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c        (revision 241795)
+++ gcc/loop-invariant.c        (working copy)
@@ -598,13 +598,17 @@ find_exits (struct loop *loop, basic_blo
 
          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: gcc/testsuite/gcc.dg/pr78185.c
===================================================================
--- gcc/testsuite/gcc.dg/pr78185.c      (revision 0)
+++ gcc/testsuite/gcc.dg/pr78185.c      (revision 0)
@@ -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;
+}

Reply via email to