On Tue, 11 Dec 2012, Jakub Jelinek wrote: > Hi! > > The following testcase on x86_64 (or the f90-intrinsic-bitsize.f on 32-bit > HWI) with -Os shows a bug in discover_iteration_bound_by_body_walk. If some > bound is a -1, -1 HWI, then adding double_int_one to it overflows into 0, 0 > HWI and we can return that as maximum number of iterations. We need to > ignore such bounds instead. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > 2012-12-11 Jakub Jelinek <ja...@redhat.com> > > PR fortran/55633 > * tree-ssa-loop-niter.c (discover_iteration_bound_by_body_walk): > Ignore bounds on which bound += double_int_one overflowed. > > * gcc.dg/torture/pr55633.c: New test. > > --- gcc/tree-ssa-loop-niter.c.jj 2012-11-21 16:00:09.000000000 +0100 > +++ gcc/tree-ssa-loop-niter.c 2012-12-11 10:56:49.890396498 +0100 > @@ -3011,7 +3011,12 @@ discover_iteration_bound_by_body_walk (s > /* Exit terminates loop at given iteration, while non-exits produce > undefined > effect on the next iteration. */ > if (!elt->is_exit) > - bound += double_int_one; > + { > + bound += double_int_one; > + /* If an overflow occurred, ignore the result. */ > + if (bound.is_zero ()) > + continue; > + } > > if (!loop->any_upper_bound > || bound.ult (loop->nb_iterations_upper_bound)) > @@ -3037,7 +3042,12 @@ discover_iteration_bound_by_body_walk (s > { > double_int bound = elt->bound; > if (!elt->is_exit) > - bound += double_int_one; > + { > + bound += double_int_one; > + /* If an overflow occurred, ignore the result. */ > + if (bound.is_zero ()) > + continue; > + } > > if (!loop->any_upper_bound > || bound.ult (loop->nb_iterations_upper_bound)) > --- gcc/testsuite/gcc.dg/torture/pr55633.c.jj 2012-12-11 11:12:19.567069030 > +0100 > +++ gcc/testsuite/gcc.dg/torture/pr55633.c 2012-12-11 11:12:04.000000000 > +0100 > @@ -0,0 +1,39 @@ > +/* PR fortran/55633 */ > +/* { dg-do run { target int128 } } */ > + > +extern void abort (void); > + > +__attribute__((noinline, noclone)) void > +bar (__int128_t *x) > +{ > + int c = sizeof (__int128_t) * __CHAR_BIT__; > + if (c > 127) > + c = 127; > + if (*x != c) > + abort (); > +} > + > +__attribute__((noinline)) void > +foo (void) > +{ > + __int128_t m, ma; > + ma = 0; > + m = 0; > + m = ~m; > + do > + { > + if (m == 0 || ma > 126) > + break; > + ma = ma + 1; > + m = ((__uint128_t) m) >> 1; > + } > + while (1); > + bar (&ma); > +} > + > +int > +main () > +{ > + foo (); > + return 0; > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE / SUSE Labs SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746 GF: Jeff Hawn, Jennifer Guild, Felix Imend