Bug 28362

Summary: [ARM] Generates wrong code for ALSA kernel driver
Product: gcc Reporter: enrico.scholz
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: normal CC: dberlin, dirk.behme, enrico.scholz, gcc-bugs, s_j_newbury
Priority: P3    
Version: 4.1.1   
Target Milestone: ---   
Host: i386-redhat-linux Target: arm-xscale-linux-gnu
Build: i386-redhat-linux Known to work:
Known to fail: 3.4.6 4.0.3 4.1.1 Last reconfirmed:

Description enrico.scholz 2006-07-12 16:53:54 UTC
gcc creates invalid code for

------
struct snd_mask {
    unsigned int bits[6];	// ****** (1) *******
};

static int snd_mask_refine(struct snd_mask *mask, const struct snd_mask *v)
{
  struct snd_mask old;

  old = *mask;
  if (mask->bits[0]==0 && mask->bits[1]==0)
    *(char *)0 = 0;

  return mask->bits[0] == old.bits[0] ? 0 : 1;
}

static int test(struct snd_mask *a, struct snd_mask *b)
{
  return snd_mask_refine(a, b);
}

int main(int argc, char *argv[])
{
  int volatile	  v    = 0;
  struct snd_mask mask;
  struct snd_mask m;


  mask.bits[0] = 23;
  mask.bits[1] = 42;
  mask.bits[2] = 0;
  mask.bits[3] = 0;
  mask.bits[4] = 0;		// ****** (2) ********
  mask.bits[5] = 0;

  m.bits[0] = 0xffffffff;
  m.bits[1] = 0xffffffff;
  m.bits[2] = 0xffffffff;
  m.bits[3] = 0xffffffff;
  m.bits[4] = 0xffffffff;
  m.bits[5] = 0xffffffff;
  
  return !v ? test(&mask, &m) : test(&m, &mask);
}
------

| $ arm-xscale-linux-gnu-gcc -Os ./test.c
| $ ./a.out
| Segmentation fault



When changing parameters things are fine; e.g.

| $ arm-xscale-linux-gnu-gcc -O0 ./test.c
| $ ./a.out
| $


Affecting parameters are:

* assigning '1' instead of '0' at (2)
* the array size at (1); e.g. 5 instead of 6 makes it work as expected
* optimization flags; e.g. '-O0' or '-O3' makes it work
* platform; can not reproduce it on non-arm compilers,


The code gnerated by '-Os' is

| 000080a0 <test>:
|     80a0:       e52de004        str     lr, [sp, #-4]!
|     80a4:       e24dd018        sub     sp, sp, #24     ; 0x18
|     80a8:       e1a0c00d        mov     ip, sp
|     80ac:       e1a0e000        mov     lr, r0
|     80b0:       e8be000f        ldmia   lr!, {r0, r1, r2, r3}
|     80b4:       e8ac000f        stmia   ip!, {r0, r1, r2, r3}
|     80b8:       e89e0003        ldmia   lr, {r0, r1}
|     80bc:       e2503000        subs    r3, r0, #0      ; 0x0
|     80c0:       e88c0003        stmia   ip, {r0, r1}
|     80c4:       e59d2000        ldr     r2, [sp]
|     80c8:       1a000001        bne     80d4 <test+0x34>
|     80cc:       e3510000        cmp     r1, #0  ; 0x0
|     80d0:       05c33000        streqb  r3, [r3]
|     80d4:       e0530002        subs    r0, r3, r2
|     80d8:       13a00001        movne   r0, #1  ; 0x1
|     80dc:       e28dd018        add     sp, sp, #24     ; 0x18
|     80e0:       e8bd8000        ldmia   sp!, {pc}


afais:

* 0x80b0 + 0x80b4 copies 'mask[0..3]' to 'old[0..3]'.
* 0x80b8 loads mask[4..5] into {r0,r1}
* now, it uses r0 which contains mask[4] but not mask[0] for comparision
  which is wrong



Bug can be reproduced with


$ $C-gcc-3.4.5 -v
Reading specs from /usr/lib/gcc/arm-xscale-linux-gnu/3.4.5/specs
Configured with: ../configure --prefix=/usr --build=i686-redhat-linux-gnu --host=i686-redhat-linux-gnu --target=arm-xscale-linux-gnu --with-sysroot=/usr/arm-xscale-linux-gnu/sys-root --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --infodir=/usr/share/info --mandir=/usr/share/man --enable-version-specific-runtime-libs --enable-languages=c,c++ --enable-shared --enable-threads --disable-multilib --with-cpu=xscale --enable-cxx-flags=-mcpu=xscale -fomit-frame-pointer
Thread model: posix
gcc version 3.4.5

$ $C-gcc-4.0.3 -v
Using built-in specs.
Target: arm-xscale-linux-gnu
Configured with: ../configure --prefix=/usr --build=i686-redhat-linux-gnu --host=i686-redhat-linux-gnu --target=arm-xscale-linux-gnu --with-sysroot=/usr/arm-xscale-linux-gnu/sys-root --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --infodir=/usr/share/info --mandir=/usr/share/man --enable-version-specific-runtime-libs --enable-languages=c --enable-shared --enable-threads --disable-multilib --with-cpu=xscale --enable-cxx-flags=-mcpu=xscale -fomit-frame-pointer
Thread model: posix
gcc version 4.0.3

$ $C-gcc-4.1.1 -v
Using built-in specs.
Target: arm-xscale-linux-gnu
Configured with: ../configure --prefix=/usr --build=i686-redhat-linux-gnu --host=i686-redhat-linux-gnu --target=arm-xscale-linux-gnu --with-sysroot=/usr/arm-xscale-linux-gnu/sys-root --disable-__cxa_atexit --enable-target-optspace --with-gnu-ld --disable-nls --infodir=/usr/share/info --mandir=/usr/share/man --enable-version-specific-runtime-libs --disable-multilib --enable-languages=c,c++,java,objc --enable-shared --enable-threads --with-cpu=xscale --enable-cxx-flags=-mcpu=xscale -fomit-frame-pointer
Thread model: posix
gcc version 4.1.1


The assembler code above was created with 4.1.1.

I think this is a major bug.
Comment 1 enrico.scholz 2006-07-15 19:22:04 UTC

*** This bug has been marked as a duplicate of 27363 ***