Message ID | 20121211183205.GT2315@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
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 <jakub@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 > >
--- 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; +}