From patchwork Wed Feb 2 15:29:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [PR,tree-optimization/45122] don't make too-unsafe loop assumptions From: Alexandre Oliva X-Patchwork-Id: 81464 Message-Id: To: gcc-patches@gcc.gnu.org Date: Wed, 02 Feb 2011 13:29:05 -0200 Given -funsafe-loop-optimizations, we used to discard the assumptions that had to hold in order for the estimated loop trip count to apply. It turns out that this is less likely to be reasonable behavior if the loop has more than one exit, because the exit with the smallest estimated trip count whose base assumption indicated it wouldn't apply would end up prevailing over another exit test for which a larger trip count was estimated, as in the given testcase. This patch stops us from discarding these assumptions (or rather, from making too-unsafe assumptions :-) when the loop has more than one exit. Regstrapped on x86_64-linux-gnu and i686-pc-linux-gnu. Ok to install? for gcc/ChangeLog from Alexandre Oliva PR tree-optimization/45122 * tree-ssa-loop-niter.c (number_of_iterations_exit): Don't make unsafe assumptions when there's more than one loop exit. for gcc/testsuite/ChangeLog from Alexandre Oliva PR tree-optimization/45122 * gcc.dg/tree-ssa/pr45122.c: New. Index: gcc/tree-ssa-loop-niter.c =================================================================== --- gcc/tree-ssa-loop-niter.c.orig 2011-02-02 02:37:44.402903056 -0200 +++ gcc/tree-ssa-loop-niter.c 2011-02-02 03:04:16.656372360 -0200 @@ -1890,7 +1890,7 @@ number_of_iterations_exit (struct loop * /* With -funsafe-loop-optimizations we assume that nothing bad can happen. But if we can prove that there is overflow or some other source of weird behavior, ignore the loop even with -funsafe-loop-optimizations. */ - if (integer_zerop (niter->assumptions)) + if (integer_zerop (niter->assumptions) || !single_exit (loop)) return false; if (flag_unsafe_loop_optimizations) Index: gcc/testsuite/gcc.dg/tree-ssa/pr45122.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/testsuite/gcc.dg/tree-ssa/pr45122.c 2011-02-02 03:31:58.678557820 -0200 @@ -0,0 +1,50 @@ +/* PR tree-optimization/27285 */ +/* PR tree-optimization/45122 */ + +/* { dg-do run } */ +/* { dg-options "-O2 -funsafe-loop-optimizations" } */ + +extern void abort (void); + +struct S { unsigned char a, b, c, d[16]; }; + +void __attribute__ ((noinline)) +foo (struct S *x, struct S *y) +{ + int a, b; + unsigned char c, *d, *e; + + b = x->b; + d = x->d; + e = y->d; + a = 0; + while (b) + { + if (b >= 8) + { + c = 0xff; + b -= 8; + } + else + { + c = 0xff << (8 - b); + b = 0; + } + + e[a] = d[a] & c; + a++; + } +} + +int +main (void) +{ + struct S x = { 0, 25, 0, { 0xaa, 0xbb, 0xcc, 0xdd }}; + struct S y = { 0, 0, 0, { 0 }}; + + foo (&x, &y); + if (x.d[0] != y.d[0] || x.d[1] != y.d[1] + || x.d[2] != y.d[2] || (x.d[3] & 0x80) != y.d[3]) + abort (); + return 0; +}