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? 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