Hello,

It seems that when a structure is 64bit large the optimizer uses a register to
store it, but does not managed the initialization of the fields properly,
leading to a wrong result at the end.

Here is my test case:
cat main.c
struct A {
   short A1 ;
   short A2 ;
   int   A3 ;
};

extern void* bar(void);

static struct A foo(void) __attribute__ ((noinline));

static struct A foo(void)
{
   struct A result;
   void *pB;

   result.A1 = (short)0;
   result.A2 = (short)0;
   /* The next field is intentionally not initialized */
   /* result.A3 = 0; */

   pB = bar(); /* always return (void*)1 to highlight the bug */
   if (pB == ((void *)0)) {
                  /* Should never been triggered at run time */
      result.A1 = (short)1;
      result.A2 = (short)2;
      result.A3 = 3;
      return result;
   }

         /* result.A1 should be (short)0 */
   return result;

}

int main(){
        struct A myA = foo();
        return (int)myA.A1; /* should always return 0 by design */
}

cat bar.c
void* bar(void){
        return (void*)1;
}

Compilation with -O0 works and the return status is 0 as expected:
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc -O0 -Wall   -c -o main.o
main.c
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc -O0 -Wall   -c -o bar.o
bar.c
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc   main.o bar.o   -o main
./main
echo $?
0

Compilation with -O1 works but the return status is 1 due to the bug:
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc -O1 -Wall   -c -o main.o
main.c
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc -O1 -Wall   -c -o bar.o
bar.c
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc   main.o bar.o   -o main
./main
echo $?
1

As the code is deterministic the result should have been 0 in both cases.

The disassembly of main.o file makes it pretty clear that the generated
optimized code is wrong:
objdump -d main.o

main.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <foo>:
   0:   48 83 ec 08             sub    $0x8,%rsp
   4:   e8 00 00 00 00          callq  9 <foo+0x9>
   9:   48 b8 01 00 02 00 03    mov    $0x300020001,%rax  <<< Value always
returned
  10:   00 00 00
  13:   48 83 c4 08             add    $0x8,%rsp
  17:   c3                      retq

0000000000000018 <main>:
  18:   48 83 ec 08             sub    $0x8,%rsp
  1c:   e8 df ff ff ff          callq  0 <foo>
  21:   98                      cwtl
  22:   48 83 c4 08             add    $0x8,%rsp
  26:   c3                      retq

As you can see in all cases the returned value of function foo is set by "mov  
 $0x300020001,%rax" whereas there should also be 2 cases.

My gcc version:
/projects/dsr/work/jetienne/softs/gcc-4.4.3/bin/gcc -v
Using built-in specs.
Target: x86_64-unknown-linux-gnu
Configured with: ./configure
--prefix=/projects/dsr/work/jetienne/softs/gcc-4.4.3 --enable-languages=c,c++
--with-mpfr=/tools/mpfr-2.4.2
Thread model: posix
gcc version 4.4.3 (GCC)

FYI I tried several gcc versions, here are the status:
- gcc 3.4.5 works
- gcc 4.1.2 works
- gcc 4.3.2 does not work
- gcc 4.4.3 does not work

I am testing the svn trunk at the moment I will get back to you with my result.

Best Regards,
Julien


-- 
           Summary: Struct to register optimization fails
           Product: gcc
           Version: 4.4.3
            Status: UNCONFIRMED
          Severity: blocker
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: julien dot etienne at gmail dot com
 GCC build triplet: x86_64-suse-linux
  GCC host triplet: x86_64-suse-linux
GCC target triplet: x86_64-suse-linux


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43629

Reply via email to