Bug 39593 - [avr] faulty value assignment
Summary: [avr] faulty value assignment
Status: RESOLVED DUPLICATE of bug 37466
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.3.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2009-03-30 23:50 UTC by Szikra Istvan
Modified: 2009-04-06 22:38 UTC (History)
3 users (show)

See Also:
Host:
Target: avr-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
preprocessed test case (1.22 KB, text/plain)
2009-03-30 23:53 UTC, Szikra Istvan
Details
compile environment (6.10 KB, application/octet-stream)
2009-03-30 23:56 UTC, Szikra Istvan
Details
test case source (1.47 KB, text/plain)
2009-03-30 23:58 UTC, Szikra Istvan
Details
compiled assembly lists (10.91 KB, application/octet-stream)
2009-03-31 00:09 UTC, Szikra Istvan
Details
junk code to reproduce the bug (615 bytes, text/plain)
2009-03-31 12:10 UTC, Szikra Istvan
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Szikra Istvan 2009-03-30 23:50:42 UTC
This is a serious bug, since the compiler produces faulty code, without any warning! It pissed me off really bad, I had to wait a month or two to calm down and prepare a half decent bug report.
It can appear anywhere and anytime. It happened with me, when I removed an unrelated line from a different portion of the code. 
(I know everything in the universe is related :) )

I was able to reproduce the bug in WinAVR 20080610, 20081205, 20090313 (gcc 4.3.0,4.3.2). In short the bug looks like this:

  TF.key32[1]=TFdw1; /// 0x04050607
 484:	 ldi	r16, 0x07	; 7
 486:	 mov	r14, r16
 488:	 ldi	r16, 0x06	; 6
 48a:	 mov	r15, r16
 48c:	 ldi	r16, 0x05	; 5
 48e:	 mov	r16, r16         ;;;;;;<---- mov	r16, r16  !!!!
 490:	 ldi	r16, 0x04	; 4  ;;;;;;<---- ldi	r16, 0x04 !!!!
 492:	 mov	r17, r16
 494:	 sts	0x0064, r14
 498:	 sts	0x0065, r15
 49c:	 sts	0x0066, r16
 4a0:	 sts	0x0067, r17
 [...]
The rest of the code is in the attached files, I tried to minimize the code, I think I left only what is needed.

The working WinAVR versions (20070525 (4.1.2), 20060421 (3.4.6) ) are just that, working, (they use different temp register r17,r19,r23,r24,r25... instead of r16, it depends on the rest of the program code) but they still miss optimization. (They might still have the bug, I just was not able to find the right test case)
The problem seems that register assignment and type are handled as a unit in (u)int32 instructions, rather than separate.
What I mean: r0-15 no immediate instructions, need temp registers, so anytime any register of the register quad used by an int32 instruction is r0-r15 it forces all registers to be handled like no-immediate registers.
what we would like is something on the line of this:

 	ldi	r16, 0x07	; 7
 	mov	r14, r16
 	ldi	r16, 0x06	; 6
 	mov	r15, r16

 	ldi	r16, 0x05	; 5  ;
 	ldi	r17, 0x04	; 4  ; instead of  ldi	r16, 0x04	+mov	r17, r16

 	sts	0x0064, r14
 	sts	0x0065, r15
 	sts	0x0066, r16
 	sts	0x0067, r17

how any "mov	r16, r16" remains in the optimized code anyway is a mystery to me :)

Thank the developers hard work!

compile command line:
avr-gcc -v -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -DBOOTSIZE=1024  -Os -save-temps  -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fno-inline-small-functions  -Wall -Winline -Wstrict-prototypes -Wa,-adhlns=vat.lst   -std=gnu99 -MD -MP -MF .dep/vat.o.d vat.c -o vat.o

Using built-in specs.
Target: avr
Configured with: ../gcc-4.3.2/configure --enable-win32-registry=WinAVR-20090313 --with-gmp=/usr/local --with-mpfr=/usr/local --prefix=/c/WinAVR --target=avr --enable-languages=c,c++,objc --with-dwarf2 --enable-doc --disable-shared --disable
-libada --disable-libssp --disable-nls --with-pkgversion='WinAVR 20090313' --with-bugurl='URL:http://sourceforge.net/tracker/?atid=520074&group_id=68108&func=browse'
Thread model: single
gcc version 4.3.2 (WinAVR 20090313)
COLLECT_GCC_OPTIONS='-v' '-c' '-mmcu=atmega16' '-I.' '-gdwarf-2' '-DF_CPU=8000000UL' '-DBOOTSIZE=1024' '-Os' '-save-temps' '-funsigned-char' '-funsigned-bitfields' '-fpack-struct' '-fshort-enums' '-fno-inline-small-functions' '-Wall' '-Winl
ine' '-Wstrict-prototypes' '-std=gnu99' '-MD' '-MP' '-MF' '.dep/vat.o.d' '-o' 'vat.o'
 e:/winavr/20090313/bin/../libexec/gcc/avr/4.3.2/cc1.exe -E -quiet -v -I. -imultilib avr5 -iprefix e:\winavr\20090313\bin\../lib/gcc/avr/4.3.2/ -MD vat.d -MF .dep/vat.o.d -MP -MQ vat.o -DF_CPU=8000000UL -DBOOTSIZE=1024 vat.c -mmcu=atmega16
-std=gnu99 -Wall -Winline -Wstrict-prototypes -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fno-inline-small-functions -fworking-directory -Os -fpch-preprocess -o vat.i
ignoring nonexistent directory "e:/winavr/20090313/lib/gcc/../../avr/sys-include"
#include "..." search starts here:
#include <...> search starts here:
 .
 e:\winavr\20090313\bin\../lib/gcc/avr/4.3.2/include
 e:\winavr\20090313\bin\../lib/gcc/avr/4.3.2/include-fixed
 e:/winavr/20090313/lib/gcc/../../lib/gcc/avr/4.3.2/include
 e:/winavr/20090313/lib/gcc/../../lib/gcc/avr/4.3.2/include-fixed
 e:/winavr/20090313/lib/gcc/../../avr/include
End of search list.
COLLECT_GCC_OPTIONS='-v' '-c' '-mmcu=atmega16' '-I.' '-gdwarf-2' '-DF_CPU=8000000UL' '-DBOOTSIZE=1024' '-Os' '-save-temps' '-funsigned-char' '-funsigned-bitfields' '-fpack-struct' '-fshort-enums' '-fno-inline-small-functions' '-Wall' '-Winl
ine' '-Wstrict-prototypes' '-std=gnu99' '-MD' '-MP' '-MF' '.dep/vat.o.d' '-o' 'vat.o'
 e:/winavr/20090313/bin/../libexec/gcc/avr/4.3.2/cc1.exe -fpreprocessed vat.i -quiet -dumpbase vat.c -mmcu=atmega16 -auxbase-strip vat.o -gdwarf-2 -Os -Wall -Winline -Wstrict-prototypes -std=gnu99 -version -funsigned-char -funsigned-bitfiel
ds -fpack-struct -fshort-enums -fno-inline-small-functions -o vat.s
GNU C (WinAVR 20090313) version 4.3.2 (avr)
        compiled by GNU C version 3.4.5 (mingw-vista special r3), GMP version 4.2.3, MPFR version 2.4.0.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: abe89850c430a90419070abaa31bf632
COLLECT_GCC_OPTIONS='-v' '-c' '-mmcu=atmega16' '-I.' '-gdwarf-2' '-DF_CPU=8000000UL' '-DBOOTSIZE=1024' '-Os' '-save-temps' '-funsigned-char' '-funsigned-bitfields' '-fpack-struct' '-fshort-enums' '-fno-inline-small-functions' '-Wall' '-Winl
ine' '-Wstrict-prototypes' '-std=gnu99' '-MD' '-MP' '-MF' '.dep/vat.o.d' '-o' 'vat.o'
 e:/winavr/20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/as.exe -mmcu=atmega16 -adhlns=vat.lst -o vat.o vat.s
COMPILER_PATH=e:/winavr/20090313/bin/../libexec/gcc/avr/4.3.2/;e:/winavr/20090313/bin/../libexec/gcc/;e:/winavr/20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/bin/
LIBRARY_PATH=e:/winavr/20090313/bin/../lib/gcc/avr/4.3.2/avr5/;e:/winavr/20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr5/;e:/winavr/20090313/bin/../lib/gcc/avr/4.3.2/;e:/winavr/20090313/bin/../lib/gcc/;e:/winavr/20090313/bin/../l
ib/gcc/avr/4.3.2/../../../../avr/lib/
COLLECT_GCC_OPTIONS='-v' '-c' '-mmcu=atmega16' '-I.' '-gdwarf-2' '-DF_CPU=8000000UL' '-DBOOTSIZE=1024' '-Os' '-save-temps' '-funsigned-char' '-funsigned-bitfields' '-fpack-struct' '-fshort-enums' '-fno-inline-small-functions' '-Wall' '-Winl
ine' '-Wstrict-prototypes' '-std=gnu99' '-MD' '-MP' '-MF' '.dep/vat.o.d' '-o' 'vat.o'
Comment 1 Szikra Istvan 2009-03-30 23:53:29 UTC
Created attachment 17561 [details]
preprocessed test case
Comment 2 Szikra Istvan 2009-03-30 23:56:23 UTC
Created attachment 17562 [details]
compile environment
Comment 3 Andrew Pinski 2009-03-30 23:57:20 UTC
 BYTE b[4];

 *((DWORD *)b) = x;


this is violating aliasing rules.  Does adding -fno-strict-aliasing allow this to work?
Comment 4 Szikra Istvan 2009-03-30 23:58:53 UTC
Created attachment 17563 [details]
test case source
Comment 5 Szikra Istvan 2009-03-31 00:09:24 UTC
Created attachment 17564 [details]
compiled assembly lists

vat_20060421.lss gcc 3.4.6
vat_20070525.lss gcc 4.1.2
vat_20080610.lss gcc 4.3.0
vat_20081205.lss gcc 4.3.2
vat_20090313.lss gcc 4.3.2
Comment 6 Szikra Istvan 2009-03-31 00:20:42 UTC
(In reply to comment #3)
>  BYTE b[4];
>  *((DWORD *)b) = x;
> this is violating aliasing rules.  Does adding -fno-strict-aliasing allow this
> to work?

If you look at the code you can see it is never called, the only code that is actually called at all is the InitTF() assignments, the rest is just junk, that confuses the compiler.

And -fno-strict-aliasing does not help, by the way the junk code works just fine, that is not the problem. Thanks anyway, I added -fno-strict-aliasing to makefile.
Comment 7 Richard Biener 2009-03-31 09:44:41 UTC
For convenience, here is the testcase reduced (I didn't verify it still "fails",
but it obviously should).

unsigned long key32[8];
void __attribute__((noinline)) InitTF(void)
{
  key32[0]=0x00010203;
  key32[1]=0x04050607;
  key32[2]=0x08091011;
  key32[3]=0x12131415;
  key32[4]=0x00010203;
  key32[5]=0x04050607;
  key32[6]=0x08091011;
  key32[7]=0x12131415;
}
void abort (void);
int main()
{
  InitTF();
  if (key32[1] != 0x04050607 || key32[5] != 0x04050607)
    abort ();
  return 0;
}

Can you check if that causes a runtime failure?  It indeed looks like a
target issue related to loading constants.
Comment 8 Szikra Istvan 2009-03-31 12:05:37 UTC
(In reply to comment #7)
> For convenience, here is the testcase reduced (I didn't verify it still
> "fails", but it obviously should).
No it should not, the junk code is necessary to produce the error. As I said before if I remove any more lines from the code, it won't produce the bug.
I suspect it's because it's massive register usage.

> Can you check if that causes a runtime failure?  It indeed looks like a
> target issue related to loading constants.
I tried your testcase, it uses r24 as a temp reg. (won't corrupt the value)
I inserted the junk code into your testcase, and the bug rearreared, but only if it is inserted before InitTF.

#include "junk.i.c"  ///BUG
unsigned long key32[8];
//#include "junk.i.c" ///BUG 
void __attribute__((noinline)) InitTF(void)
{
  key32[0]=0x00010203;
  key32[1]=0x04050607;
  key32[2]=0x08091011;
  key32[3]=0x12131415;
  key32[4]=0x00010203;
  key32[5]=0x04050607;
  key32[6]=0x08091011;
  key32[7]=0x12131415;
}
//#include "junk.i.c"  ///r24
void abort (void);
int main()
{
  InitTF();
  if (key32[1] != 0x04050607 || key32[5] != 0x04050607)
    abort ();
  return 0;
}
//#include "junk.i.c"   ///r24

Comment 9 Szikra Istvan 2009-03-31 12:10:59 UTC
Created attachment 17570 [details]
junk code to reproduce the bug

this is a reduced portion of the original program and the simplest that still generates the bug
Comment 10 Eric Weddington 2009-04-06 22:38:07 UTC
This looks like a duplicate of bug #37466.

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