Hello GCC bug hunters, I'm using GCC C compiler, compiled as a cross compiler for AVR (ATmel microcontrollers) on Cygwin (Windows). With earlier GCC version 4.1.2 always smaller code was generated for one of the projects I'm working on than with more recent versions of GCC. I tested with GCC 4.2.x a while ago and more recently with GCC 4.3.3 (snapshot) and GCC 4.4 (snapshot also).
Since I'm mostly adding patches to GCC from the WinAVR project, I prepared a freshly compiled GCC 4.3.3 (20081219) without these patches for this bug report over here. The following is the version output of the compiler for my tests: #> avr-gcc43 -v Using built-in specs. Target: avr Configured with: ../gcc-4.3-20081218/configure --prefix=/usr/local --target=avr --program-prefix=avr- --program-suffix=43 --enable-languages=c --disable-libssp Thread model: single gcc version 4.3.3 20081218 (prerelease) (GCC) Failure description: GCC 4.3.3 does automatically inline (many) functions, when optimization setting "-O2" is used. It even inlines static functions that are called several times from all over the code within the same module. This heavily increases code size. Even worse, this code blowing automatic inline is also done with optimzation setting "-Os" and therefore contradicts this optimization setting. With GCC-4.1.2 this code increase because of (too much) automatic function inlining could not be observed, although even GCC-4.1.2 does some automatic inlining. Here's a stripped down code sample to demonstrate the bug: /* * License: GPL * Copyright: (c) 2007 by Till Harbaum <t...@harbaum.org> * Copyright: (c) 2008 Wolfgang Moser, http://d81.de */ /* #include <avr/wdt.h> */ /* some declarations from the include above for ATMega8 */ #define _SFR_IO8(io_addr) (*(volatile unsigned char *)((io_addr) + 0x20)) #define TOV0 0 #define TCNT0 _SFR_IO8(0x32) #define TIFR _SFR_IO8(0x38) #define DDRC _SFR_IO8(0x14) #define DDRD _SFR_IO8(0x11) #define PORTC _SFR_IO8(0x15) #define PORTD _SFR_IO8(0x12) static void delay_wait_us( unsigned char timeout ) { __asm__ __volatile__ ("wdr"); TCNT0 = timeout; TIFR |= (1 << (TOV0)); /* wait until counter overflows */ while(!(TIFR & (1 << (TOV0)))); } static void delay_wait_us_ms( unsigned char timeout ) { delay_wait_us( timeout * 1000 ); } void makeUseOfTimerWait( unsigned char val ) { delay_wait_us( 10 ); DDRC |= 0x10; delay_wait_us( 10 ); DDRD |= 0x20; delay_wait_us( 20 ); PORTC &= ~0x10; delay_wait_us( 10 ); PORTD &= ~0x20; delay_wait_us_ms( 5 ); PORTC |= val & 0x10; delay_wait_us( 10 ); PORTD |= val & 0x20; delay_wait_us( 10 ); } Compiling this sample with: #> avr-gcc43 -save-temps -c -Wall -Os -mmcu=atmega8 autoinline.c leads to the following module components: #> avr-nm -S --size-sort autoinline.o 00000000 0000009c T makeUseOfTimerWait Both static functions, delay_wait_us() as well as delay_wait_ms() were inlined, although the GCC manual clearly states that automatic function inlining would only be enabled for optimization "-O3" of greater. Normally, when optimizing for size with "-Os" (but also, when using "-O1" or "-O2"), at least I would expect that at most functions are inlined that do not increase code size. For the example above and setting "-Os", function delay_wait_ms() may be inlined, because it is used only once. But function delay_wait_us() must not be inlined. This behavior could be provoked by setting special GCC internal configuration parameters like e.g.: #> avr-gcc43 -save-temps --param max-inline-insns-auto=4 -c -Wall -Os -mmcu=atmega8 autoinline.c #> avr-nm -S --size-sort autoinline.o 00000000 00000012 t delay_wait_us 00000012 0000003e T makeUseOfTimerWait That way code size reduce to 0x12+0x3e=0x50 instead of 0x9c (only taking function symbols into account). With kind regards, Wolfgang Moser -- Summary: gcc version 4.2.x, 4.3.x and 4.4.0 are doing (too much) automatic inlining with -O1, -O2 and -Os Product: gcc Version: 4.3.3 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: cbm at d81 dot de GCC build triplet: i386/cygwin GCC host triplet: i386/cygwin GCC target triplet: avr http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38629