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

Reply via email to