[arch-general] gcc: loop do not terminate

goodmenzy at gmail.com goodmenzy at gmail.com
Tue May 14 04:47:24 EDT 2013


On 2013-05-13 18:20:05, LANGLOIS Olivier PIS -EXT wrote:
> Date: Mon, 13 May 2013 18:20:05 +0000
> From: LANGLOIS Olivier PIS -EXT <olivier.pis.langlois at transport.alstom.com>
> To: "General Discussion about Arch Linux (arch-general at archlinux.org)"
>  <arch-general at archlinux.org>
> Subject: [arch-general] gcc: loop do not terminate
> 
> I have just been hit by something:
> 
> lano1106 at hpmini ~/dev/gcc-test $ g++ --version
> g++ (GCC) 4.8.0 20130502 (prerelease)
> Copyright (C) 2013 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> 
> lano1106 at hpmini ~/dev/gcc-test $ g++ -O2 -o test1 test1.cpp test1_init.cpp
> lano1106 at hpmini ~/dev/gcc-test $ ./test1
> item 0
>  a: 1
> lano1106 at hpmini ~/dev/gcc-test $ g++ -O1 -o test1 test1.cpp test1_init.cpp
> lano1106 at hpmini ~/dev/gcc-test $ ./test1
> item 0
>  a: 1

  I have checked the disassemble of -O1 result,
in fact, the for-loop seems optimized out. Not increasment operation(++i),
and not jump to the loop begining:

        for( int i = 0; i < arr[0].numelem; ++i )
  4005df:       8b 14 24                mov    (%rsp),%edx
  4005e2:       85 d2                   test   %edx,%edx
  4005e4:       7e 1b                   jle    400601 <main+0x41>
        {
                printf( "item %d/%d: a = %d\n",
                        i,
                        arr[0].numelem,
                        122 + arr[0].item[i].a
                                );
  4005e6:       8b 44 24 04             mov    0x4(%rsp),%eax
  4005ea:       8d 48 7a                lea    0x7a(%rax),%ecx
  4005ed:       be 00 00 00 00          mov    $0x0,%esi
  4005f2:       bf b4 06 40 00          mov    $0x4006b4,%edi
  4005f7:       b8 00 00 00 00          mov    $0x0,%eax
  4005fc:       e8 9f fe ff ff          callq  4004a0 <printf at plt>
        }

        return 0;
}
  400601:       b8 00 00 00 00          mov    $0x0,%eax
  400606:       48 81 c4 48 01 00 00    add    $0x148,%rsp
  40060d:       c3                      retq   
  40060e:       66 90                   xchg   %ax,%ax

any one can help to explain it?


> lano1106 at hpmini ~/dev/gcc-test $ g++ -O0 -o test1 test1.cpp test1_init.cpp
> lano1106 at hpmini ~/dev/gcc-test $ ./test1
> item 0
>  a: 1
> item 1
>  a: 2
> lano1106 at hpmini ~/dev/gcc-test $ cat test1.h
> 
> struct A
> {
>         int a;
>         int b;
>         int c;
> };
> 
> struct B
> {
>         int numelem;
>         /*
>          * Old C trick to define a dynamically sizable array just by allocating
>          * sizeof(B) + (numelem-1)*sizeof(A) memory.
>          */
>         A   item[1];
> };
> 
> void initArr(B *p);
> 
> lano1106 at hpmini ~/dev/gcc-test $ cat test1_init.cpp
> #include "test1.h"
> 
> void initArr(B *p)
> {
>         p->numelem = 2;
>         p->item[0].a = 1;
>         p->item[1].a = 2;
> }
> 
> lano1106 at hpmini ~/dev/gcc-test $ cat test1.cpp
> /*
>  * Author: Olivier Langlois <olivier at trillion01.com>
>  *
>  * Purpose: Small test to highlight gcc optimization bug
>  */
> 
> #include <stdio.h>
> #include <string.h>
> #include "test1.h"
> 
> /*
>  * Create a B array with the intent of only using the first item.
>  * The 19 other items sole purpose is to create a buffer large enough
>  * to accomodate A array needs.
>  */
> #define MAXBLEN 20
> 
> int main(int argc, char *argv[])
> {
>         B arr[MAXBLEN];
>         memset(arr,0,sizeof(arr));
> 
>         initArr(arr);
> 
>         for( int i = 0; i < arr[0].numelem; ++i )
>         {
>                 printf( "item %d\n"
>                         " a: %d\n",
>                         i,
>                         arr[0].item[i].a);
>         }
> 
>         return 0;
> }
> 
> From gcc website, this is not a bug:
> 
> Loops do not terminate
> 
>     This is often caused by out-of-bound array accesses or by signed integer overflow which both result in undefined behavior according to the ISO C standard. For example
> 
>         int
>         SATD (int* diff, int use_hadamard)
>         {
>           int k, satd = 0, m[16], dd, d[16];
>           ...
>             for (dd=d[k=0]; k<16; dd=d[++k])
>               satd += (dd < 0 ? -dd : dd);
> 
>     accesses d[16] before the loop is exited with the k<16 check. This causes the compiler to optimize away the exit test because the new value of k must be in the range [0, 15] according to ISO C.
> 
>     GCC starting with version 4.8 has a new option -fno-aggressive-loop-optimizations that may help here. If it does, then this is a clear sign that your code is not conforming to ISO C and it is not a GCC bug.
> 
> I am surprised that I didn't hit the problem before but I am seriously considering using '-fno-aggressive-loop-optimizations' in my own makepkg.conf. I just want to test others feeling on this discovery to see if it wouldn't be a good idea to make the switch standard in Arch...
> 
> 
> ________________________________
> CONFIDENTIALITY : This e-mail and any attachments are confidential and may be privileged. If you are not a named recipient, please notify the sender immediately and do not disclose the contents to another person, use it for any purpose or store or copy the information in any medium.



More information about the arch-general mailing list