On Tue, 30 Jan 2018, Jakub Jelinek wrote: > On Tue, Jan 30, 2018 at 08:59:43AM +0100, Richard Biener wrote: > > The issue is that > > > > static bool > > tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, > > bitmap father_bbs, struct loop *loop) > > { > > struct loop *loop_father; > > bool changed = false; > > struct loop *inner; > > enum unroll_level ul; > > > > /* Process inner loops first. */ > > for (inner = loop->inner; inner != NULL; inner = inner->next) > > changed |= tree_unroll_loops_completely_1 (may_increase_size, > > unroll_outer, father_bbs, > > inner); > > > > when recursing tree_unroll_loops_completely_1 appends unrolled > > bodies and loops contained therein in the loop->inner chain. We > > specifically do _not_ allow processing of outer loops here due > > to not up-to-date SSA form and then iterate the unrolling process > > instead: > > > > /* If we changed an inner loop we cannot process outer loops in this > > iteration because SSA form is not up-to-date. Continue with > > siblings of outer loops instead. */ > > if (changed) > > return true; > > > > so I think the proper fix is to avoid visiting loops that were added > > in the above iteration over loop->inner. For example by collecting > > the loop->inner chain in a vec and then iterating over that (much > > like FOR_EACH_LOOP does). Or rely on the fact that loop->num of new > > loops will be >= number_of_loops () [number_of_loops () is really > > mis-named, would be a good time to add max_loop_num () or so] > > So like this if it passes bootstrap/regtest?
Yes. > OT, why is loop->num signed rather than unsigned? History. Like so many others (block->index, etc.). Possibly to allow better optimization of loops over those indexes (relying on undefined overflow). Richard. > 2018-01-30 Richard Biener <rguent...@suse.de> > Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/84111 > * tree-ssa-loop-ivcanon.c (tree_unroll_loops_completely_1): Skip > inner loops added during recursion, as they don't have up-to-date > SSA form. > > * gcc.c-torture/compile/pr84111.c: New test. > > --- gcc/tree-ssa-loop-ivcanon.c.jj 2018-01-29 14:05:46.689153783 +0100 > +++ gcc/tree-ssa-loop-ivcanon.c 2018-01-30 09:30:21.932069737 +0100 > @@ -1373,13 +1373,17 @@ tree_unroll_loops_completely_1 (bool may > bool changed = false; > struct loop *inner; > enum unroll_level ul; > + unsigned num = number_of_loops (cfun); > > - /* Process inner loops first. */ > + /* Process inner loops first. Don't walk loops added by the recursive > + calls because SSA form is not up-to-date. They can be handled in the > + next iteration. */ > for (inner = loop->inner; inner != NULL; inner = inner->next) > - changed |= tree_unroll_loops_completely_1 (may_increase_size, > - unroll_outer, father_bbs, > - inner); > - > + if ((unsigned) inner->num < num) > + changed |= tree_unroll_loops_completely_1 (may_increase_size, > + unroll_outer, father_bbs, > + inner); > + > /* If we changed an inner loop we cannot process outer loops in this > iteration because SSA form is not up-to-date. Continue with > siblings of outer loops instead. */ > --- gcc/testsuite/gcc.c-torture/compile/pr84111.c.jj 2018-01-29 > 20:38:10.236528914 +0100 > +++ gcc/testsuite/gcc.c-torture/compile/pr84111.c 2018-01-29 > 20:37:53.227522763 +0100 > @@ -0,0 +1,31 @@ > +/* PR tree-optimization/84111 */ > + > +void > +foo (int x, int y, int z) > +{ > + int a = 0; > + int *b = &x; > + > + while (a < 1) > + { > + int c = y; > + *b = x; > + lab: > + for (a = 0; a < 36; ++a) > + { > + *b = 0; > + if (x != 0) > + y = 0; > + while (c < 1) > + ; > + } > + } > + if (z < 33) > + { > + b = (int *) 0; > + ++y; > + ++z; > + if (x / *b != 0) > + goto lab; > + } > +} > > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)