This may be related to bug 19001 (loops with power of two step and variable bounds not unrolled) Neither of the following empty loops is eliminated: void foo(int a, int b) { for(;a!=b;a+=4); } void foo(int a, int b) { for(;a<b;a+=4); } Similarily to 19001, these loops come about because of iterating over an range of pointers doing something for each element (for example deleting them) which for some types turns out to be a null operation. Fixing this will allow a large number of workarounds in libstdc++ to be removed.
With -funsafe-loop-optimizations we remove them. Using -Wunsafe-loop-optimizations, we get: t.c:2: warning: cannot optimize loop, the loop counter may overflow I mentioned this before to transform the loops such that we know if they overflow or not and Zdenek said it was not useful which I feel is still wrong.
*** Bug 23362 has been marked as a duplicate of this bug. ***
See http://gcc.gnu.org/ml/gcc-patches/2005-06/msg02275.html which is the email I was talking about.
Subject: Re: Can't eliminate empty loops with power of two step and variable bounds On Fri, 2005-08-12 at 19:10 +0000, pinskia at gcc dot gnu dot org wrote: > ------- Additional Comments From pinskia at gcc dot gnu dot org 2005-08-12 19:10 ------- Personally, i think -funsafe-loop-optimizations should be on by default in -O3, with a warning for when we rely on it. It's *incredibly* rare that a user actually intends for a loop counter to be able to overflow.
One thing is that if 'a' and 'b' are originally pointers of the same type, it should be clear the the loop can be removed. When they are lowered to integers, instead, we lose the precious alignment information. Can't the empty loop be removed before the pointers are lowered? Or am I missing something?
if these ints are signed, you should be able to remove these loops.
Expanding slightly, I tried the following 4 functions. All were removed by -funsafe-loop-optimisations, but only foo3 was removed by -O3 without -funsafe-loop-optimisations. I can't see a good reason to remove foo3 but not remove foo4? void foo(int a, int b) { for(;a!=b;a+=4); } void foo2(int a, int b) { for(;a<b;a+=4); } void foo3(int*a, int* b) { for(;a<b;a++); } void foo4(int*a, int*b) { for(;a!=b;a++); }
(In reply to comment #1) > With -funsafe-loop-optimizations we remove them. > Using -Wunsafe-loop-optimizations, we get: > t.c:2: warning: cannot optimize loop, the loop counter may overflow If the loop counter will overflow for signed types, that is undefined and we should do it no matter what unless -fwrapv is turned on.
Referring to Comment #7, currently in mainline, 4_2-branch and even 4.1.1 the only loop not eliminated at -O2 is foo2 - actually, that is pretty good for the library: very nice that we don't need special code to avoid foo4. Anyway, should we eliminate foo2 too?
Hello, (In reply to comment #8) > (In reply to comment #1) > > With -funsafe-loop-optimizations we remove them. > > Using -Wunsafe-loop-optimizations, we get: > > t.c:2: warning: cannot optimize loop, the loop counter may overflow > > If the loop counter will overflow for signed types, that is undefined and > we should do it no matter what unless -fwrapv is turned on. actually, the warning is missleading here. The problem is that the number of iterations of this loop is ((unsigned) b - (unsigned) a + 3) / 4 but this formula does not work if (unsigned) b - (unsigned) a + 3 overflows, which is what we fail to verify. The obvious-looking solution is to use formula 1 + ((unsigned) b - (unsigned) a -1) / 4 that does not suffer from this problem. I tried that, there are some problems with this as well (but I forgot what the problems are, so I will need to check again).
Patch: http://gcc.gnu.org/ml/gcc-patches/2007-02/msg00704.html
Subject: Bug 23361 Author: rguenth Date: Fri Feb 9 13:29:11 2007 New Revision: 121742 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=121742 Log: 2007-02-09 Zdenek Dvorak <dvorakz@suse.cz> Richard Guenther <rguenther@suse.de> PR middle-end/23361 * fold-const.c (fold_comparison): Handle obfuscated comparisons against INT_MIN/INT_MAX. * tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump file if a loop is removed. * gcc.dg/fold-compare-3.c: New testcase. * gcc.dg/tree-ssa/loop-24.c: Likewise. Added: trunk/gcc/testsuite/gcc.dg/fold-compare-3.c trunk/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa-loop-ivcanon.c
Fixed.