This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
avr-gcc generating really dumb code
- From: Ralph Doncaster <ralphdoncaster at gmail dot com>
- To: gcc at gcc dot gnu dot org
- Date: Wed, 29 Apr 2015 00:26:49 -0300
- Subject: avr-gcc generating really dumb code
- Authentication-results: sourceware.org; auth=none
I wrote a small function to convert u8 to hex:
// converts 4-bit nibble to ascii hex
uint8_t nibbletohex(uint8_t value)
{
if ( value > 9 ) value += 'A' - '0';
return value + '0';
}
// returns value as 2 ascii characters in a 16-bit int
uint16_t u8tohex(uint8_t value)
{
uint16_t hexdigits;
uint8_t hidigit = (value >> 4);
hexdigits = (nibbletohex(hidigit) << 8);
uint8_t lodigit = (value & 0x0F);
hexdigits |= nibbletohex(lodigit);
return hexdigits;
}
I compiled it with avr-gcc -Os using 4.8 and 5.1 and got the same code:
0000007a <u8tohex.1416>:
7a: 28 2f mov r18, r24
7c: 22 95 swap r18
7e: 2f 70 andi r18, 0x0F ; 15
80: 2a 30 cpi r18, 0x0A ; 10
82: 08 f0 brcs .+2 ; 0x86 <u8tohex.1416+0xc>
84: 2f 5e subi r18, 0xEF ; 239
86: 20 5d subi r18, 0xD0 ; 208
88: 30 e0 ldi r19, 0x00 ; 0
8a: 32 2f mov r19, r18
8c: 22 27 eor r18, r18
8e: 8f 70 andi r24, 0x0F ; 15
90: 8a 30 cpi r24, 0x0A ; 10
92: 08 f0 brcs .+2 ; 0x96 <u8tohex.1416+0x1c>
94: 8f 5e subi r24, 0xEF ; 239
96: 80 5d subi r24, 0xD0 ; 208
98: a9 01 movw r20, r18
9a: 48 2b or r20, r24
9c: ca 01 movw r24, r20
9e: 08 95 ret
There's some completely pointless code there, like loading 0 to r19
and immediately overwriting it with the contents of r18 (88, 8a).
Other register use is convoluted. The compiler should at least be
able to generate the following code (5 fewer instructions):
28 2f mov r18, r24
22 95 swap r18
2f 70 andi r18, 0x0F ; 15
2a 30 cpi r18, 0x0A ; 10
08 f0 brcs .+2 ; 0x86 <u8tohex.1416+0xc>
2f 5e subi r18, 0xEF ; 239
20 5d subi r18, 0xD0 ; 208
32 2f mov r25, r18
8f 70 andi r24, 0x0F ; 15
8a 30 cpi r24, 0x0A ; 10
08 f0 brcs .+2 ; 0x96 <u8tohex.1416+0x1c>
8f 5e subi r24, 0xEF ; 239
80 5d subi r24, 0xD0 ; 208
08 95 ret
Hand-optimized for size I was able to write it with 3 fewer instructions:
.macro addi Rd, K
subi \Rd, -(\K)
.endm
.global u8tohex
u8tohex:
mov r0, r24
swap r24
rcall nibbletohex ; convert hi digit
mov r25, r24
mov r24, r0
; fall into nibbletohex to convert lo digit
; convert lower nibble of byte to ascii hex char
nibbletohex:
andi r24, 0x0F
cpi r24, 10
brlo under10
addi r24, 'A'-'0';
under10:
addi r24, '0'
ret
I have no intention of learning Gimple and the internals of the gcc
back-end, but maybe someone from Atmel can fix this?