Bug 39510 - [avr] missed optimisation with IO read and register variables
Summary: [avr] missed optimisation with IO read and register variables
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: 4.3.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2009-03-20 03:13 UTC by Krzysztof Kościuszkiewicz
Modified: 2009-08-21 20:10 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.3.3 4.3.2
Last reconfirmed: 2009-08-21 20:10:06


Attachments
Second test case with void functions. (106 bytes, text/plain)
2009-03-27 17:47 UTC, Krzysztof Kościuszkiewicz
Details
Preprocessed source of test case (627 bytes, text/plain)
2009-03-28 05:55 UTC, Krzysztof Kościuszkiewicz
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Kościuszkiewicz 2009-03-20 03:13:23 UTC
Code:

#include <avr/io.h>

register uint8_t test asm("r2");

int main(void)
{
    test = TCNT0;
}

Compiled with -Os results in the following instruction sequence:

00000092 <main>:
  92:	82 b7       	in	r24, 0x32	; 50
  94:	28 2e       	mov	r2, r24
  96:	08 95       	ret

This is particularly nasty for naked interrupts, where one would expect the compiler to generate just a single instruction:
  
  in  r2, 0x32

Apparently the compiler behaves correctly when opposite transfer is requested, generating single OUT opcode.
Comment 1 Eric Weddington 2009-03-27 17:06:12 UTC
This bug is invalid.

Your test code is in main() which returns an int. The return value is stored in r24. So the code is correct to store the value in both r2 (test) and r24.

See the avr-libc user manual, FAQ, for more information on the calling convention:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage

Perhaps you need to try this in a function that has void return.
Comment 2 Krzysztof Kościuszkiewicz 2009-03-27 17:46:17 UTC
I can't see how register usage and calling convention affect this.

As I said before, this behaviour bit me in a naked interrupt handler, with no arguments and no return value.

I'm attaching a fixed test case where functions have no arguments and void return type.

#include <avr/io.h>

register uint8_t test asm("r2");

void fun1(void)
{
    test = TCNT0;
}

void fun2(void)
{
    TCNT0 = test;
}

Compile with -Os. Generated instruction sequence:

00000000 <fun1>:
   0:	82 b7       	in	r24, 0x32	; 50
   2:	28 2e       	mov	r2, r24
   4:	08 95       	ret

00000006 <fun2>:
   6:	22 be       	out	0x32, r2	; 50
   8:	08 95       	ret
Comment 3 Krzysztof Kościuszkiewicz 2009-03-27 17:47:27 UTC
Created attachment 17545 [details]
Second test case with void functions.
Comment 4 Andrew Pinski 2009-03-28 05:22:33 UTC
This might be the case hard registers are not always copy propogated except into inline-asm.  Can you provide the preprocessed source?
Comment 5 Krzysztof Kościuszkiewicz 2009-03-28 05:55:00 UTC
Created attachment 17553 [details]
Preprocessed source of test case

Created with "avr-gcc -v -save-temps -mmcu=attiny13 -Os -c test.c -o test.o"
Comment 6 Eric Weddington 2009-08-21 20:10:06 UTC
Confirmed on 4.3.2.