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; +}