Bug 37466 - [AVR] avr-gcc generating incorrect assembly for expression with the long constant operands
Summary: [AVR] avr-gcc generating incorrect assembly for expression with the long cons...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.2.2
: P3 normal
Target Milestone: 4.3.3
Assignee: aesok
URL:
Keywords: wrong-code
: 39593 (view as bug list)
Depends on:
Blocks:
 
Reported: 2008-09-10 19:30 UTC by aesok
Modified: 2009-04-06 22:42 UTC (History)
3 users (show)

See Also:
Host:
Target: avr-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-09-10 19:33:50


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description aesok 2008-09-10 19:30:19 UTC
Reported by geckosenator on avrfreaks.net


Code:

int sat; 

static volatile long data[3]; 
static volatile int datacount[3]; 

static volatile int chan; 
static volatile long val; 

int __attribute__((always_inline)) transfer(int data) 
{ 
   return (*(int *)((0x00))); 
} 

int init_status; 

long read_scale(void) 
{ 
   long val; 
   if(init_status) 
      val |= (long)transfer(0) << 16; 
   val |= (long)transfer(0) << 8; 
   return val; 
} 

void get_mode(int *mode, int *psw) 
{ 
    int val = transfer(0); 
    *psw = val & 0x10 ? 1 : 0; 
} 

long __attribute__((always_inline)) read_data(void) 
{ 
   long val; 

   val <<= 8; 
   if(init_status) 
      val |= transfer(0); 

   return val - 0x80; 
} 

void function1() 
{ 
    long data2 = read_data(); 
    sat = (data2 > 1) || (data2 < -100); 
    val += data2; 
    data[chan] += val; 
    datacount[chan] ++; 
} 

void function2(long *data) 
{ 
    int i, j; 
    data[i] += i + j; 
} 




Compile with: 

Code:

avr-gcc -std=gnu99 -fgnu89-inline -Os -mmcu=at90usb1287 -c testcase.c -o testcase.S -S 



Then look in testcase.S for: 

Code:

.L16: 
   ldi r16,lo8(-128) 
   mov r14,r16 
   ldi r16,hi8(-128) 
   mov r15,r16 
   ldi r16,hlo8(-128) 
   mov r16,r16    <-----  bad, this does nothing! 
   ldi r16,hhi8(-128) <-- nice, we just clobbered r16 
   mov r17,r16 
   add r14,r18 
   adc r15,r19 
   adc r16,r20 
   adc r17,r21 
   sts (sat)+1,__zero_reg__ 



It looks like the compiler got confused and tried to use r16 in two different ways at the same time. 


The bug occurs in peephole optmisation. Here avr-gcc looks for a spare register R16-R31 that it can use to load a constant value into operands which are located in lower register (R2-R15). 

The test for "spare" occurred before instruction. So if the instruction happened to use that register (because it was spare), bad things happen.Typically this will happen with long - or long long registers.
Comment 1 aesok 2008-09-12 16:46:49 UTC
Subject: Bug 37466

Author: aesok
Date: Fri Sep 12 16:45:34 2008
New Revision: 140321

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140321
Log:
	PR target/37466
	* config/avr/avr.md (movsi_lreg_const peephole2): Add match_dup for
	scratch register after 'set' pattern.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/avr/avr.md

Comment 2 aesok 2008-09-12 17:30:56 UTC
Subject: Bug 37466

Author: aesok
Date: Fri Sep 12 17:29:38 2008
New Revision: 140323

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=140323
Log:
	PR target/37466
	* config/avr/avr.md (movsi_lreg_const peephole2): Add match_dup for
	scratch register after 'set' pattern.

Modified:
    branches/gcc-4_3-branch/gcc/ChangeLog
    branches/gcc-4_3-branch/gcc/config/avr/avr.md

Comment 3 aesok 2008-09-12 17:36:41 UTC
Fixed.
Comment 4 Eric Weddington 2009-04-06 22:38:07 UTC
*** Bug 39593 has been marked as a duplicate of this bug. ***