https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71769
amker at gcc dot gnu.org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |amker at gcc dot gnu.org --- Comment #3 from amker at gcc dot gnu.org --- (In reply to nightstrike from comment #0) > Created attachment 38834 [details] > Testcase > > In the attached testcase, function f compiles without warning for -O[023], > but function g warns for -O[0123]. The warning is "warning: cannot optimize > possibly infinite loops [-Wunsafe-loop-optimizations]". The functions are > very similar, and I don't think it should warn in either case, as the > conditionals verify that the loop isn't infinite. > > $ gcc -v > Using built-in specs. > COLLECT_GCC=gcc > COLLECT_LTO_WRAPPER=/opt/gcc6/bin/../libexec/gcc/x86_64-pc-linux-gnu/6.1.0/ > lto-wrapper > Target: x86_64-pc-linux-gnu > Configured with: ../gcc-6.1.0/configure --prefix=/gcc6 > --enable-libstdcxx-time=rt --disable-multilib > --enable-languages=all,ada,obj-c++ --enable-plugins --with-gnu-as > --with-gnu-ld > Thread model: posix > gcc version 6.1.0 (GCC) > > $ gcc -c -std=gnu99 a.c -Wunsafe-loop-optimizations -O3 > > a.c: In function āgā: > a.c:18:2: warning: cannot optimize possibly infinite loops > [-Wunsafe-loop-optimizations] > for(int i = a; i <= b; ++i) > ^~~ > > $ cat a.c > // Warning with -Wunsafe-loop-optimizations and -O1 only > void f(int * x, int a, int b) { > if (b < a) b = a; > if (a < 1) return; > > for (int i = a; i <= b; ++i) > x[i] += 1; > } > > struct S { > unsigned int * data; > unsigned int * d2; > }; > > // Warning with -Wunsafe-loop-optimizations and -O1 or above > void g(struct S * x, int a, int b) { > if (b < a) b = a; > if (a < 1) return; > > for(int i = a; i <= b; ++i) > __builtin_memcpy(x->data, x->d2, 5); > } Well, the two loops have subtle difference here. Because function call __bultin_memcpy has side effect and could exit the loop directly, it's possible for variable "b" equals to MAX_VALUE_OF(int) int the second loop without triggering any undefined overflow behavior. From loop niter analyzer's point of view, it has to analyze the loop with assumption that "b != MAX_VALUE_OF(int)". Unfortunately, GCC in effect doesn't use niter information with assumptions in various loop optimizations. This could be seen as a missed optimization opportunities. Currently GCC computes exit_must_be_taken in loop_only_exit_p and considers side-effect function calls. There is one way around, we could accept side-effect function calls and analyze the loop as normal ones. In this case, the user of niter information needs to take the responsibility deciding the niter information can be used in code transform. IVOPT has already done this in iv elimination. Having this said, I tend to keep the current behavior because: 1) It might not be very useful. One application would be in ivcanon pass, but I can't come up other optimizer that can benefit from this. 2) This complicates customers of niter analyzer. They need to check if new undefined overflow behavior is introduced. Might be easier to handle it in niter analyzer, with a little cost of missed ivcanon (or some other optimizations?)