Optimizing with GCC

nobody wrote on Tuesday, June 06, 2006:

Hi,

I have a _VERY_ small program here : A FreeRTOS kernel running one single task (besides idle), where 4 LEDs are blinking. The thing is that the program takes up 44400 bytes !!!
The MAP file tells me that a lot of unused functions still are in the hex-file. Functions like AT91F_UDP_GetInterruptMaskStatus from lib_AT91SAM7S256.h and "/cygdrive/c/gnuarm/bin/…/lib/gcc/arm-elf/4.1.0/interwork/libgcc.a(_udivsi3.o)"

What do I do in order to remove the dead code ?

/RaceMouse

nobody wrote on Tuesday, June 06, 2006:

Yuk.  Sound like you have the whole C library library included in your executable.  I presume you are not doing any division (other than compile time constants)?

Which GCC distribution are you using?  Is it one targeted at embedded?

nobody wrote on Tuesday, June 06, 2006:

Hi,

It’s:
arm-elf-gcc 4.1.0
Binutils 2.16.1
Newlib 1.14.0

Basically it’s GnuArm - latest…

/RaceMouse

nobody wrote on Tuesday, June 06, 2006:

I am also using the latest gnuarm.  When I compile the LPC2106 demo I get a bin file (after objcopying the default elf file to bin) that is 15K.  This is the whole unmodified demo.

Which sam7 project are your compiling?  Is it in the download so I can try it?

nobody wrote on Tuesday, June 06, 2006:

It’s the lwIP_Rowley, where I have removed all lwip/usb and the just addad the one task blinking the LEDs. I changed the heap size to 3000 and changed the AT91SAM7X256 to AT91SAM7S256.

/RaceMouse

nobody wrote on Tuesday, June 06, 2006:

I checked the size on the LPC2106_GCC build and i was the ~17K. I cannot, however, seem to find any relevant diffs in the two Makefiles. The Linkerfils from the two projects are also identical (Except the RAM/ROM mapping off course)…

Any Ideas ?

/RaceMouse

nobody wrote on Tuesday, June 06, 2006:

Not that it helps but I get the same result as you.  I removed all lwIP, demo, emac and usb references from the makefile and edited main so only the setup hardware and check task remains.  I get a 42K binary.  Very odd.  I will take a look at the map file also.  Must be the atmel library?

nobody wrote on Tuesday, June 06, 2006:

Using CrossWorks the demo comes to 8K once the lwIP stuff is removed.

nobody wrote on Tuesday, June 06, 2006:

Ill’ be damned !

So - what is the difference between a normal CLI built executable and one built using Crossworks ?

Crossworks don’t use the Makefile, do they ?

Is there any way to see what commands they use with GCC ?

/RaceMouse

rtel wrote on Tuesday, June 06, 2006:

In FreeRTOSConfig.h, set configUSE_TRACE_FACILITY to 0.  I think this might make a big difference as the trace facility will pull in lot of string handling functions which GCC is not very efficient at.

There are ways of controlling this, I read a thread on it somewhere recently but I cannot remember where unfortunately.

Let me know if this sorts out your problem.

Regards.

nobody wrote on Tuesday, June 06, 2006:

Well, It definately helped a lot. The executable size has now dropped from ~44K to ~9K, so we are getting there…

The following is a snippet from the MAP file:
.text          0x001004ec      0xe04 lib_AT91SAM7S256_.o
                0x00100cac                AT91F_UDP_EpClear
                0x00100cd8                AT91F_UDP_GetInterruptMaskStatus
                0x001010fc                AT91F_PWMC_IsInterruptMasked
                0x001006ec                AT91F_CKGR_EnableMainOscillator

Only a couple of the functions in lib_AT91SAM7S256_ are used and yet they are all included by in the executable. Do you have any idea how I can eliminate them ?

/RAceMouse

rtel wrote on Tuesday, June 06, 2006:

I have got my build down to 5.5K, quite nice really :wink:

Looking in the map file there are no AT91 functions at all.

Looking in the code I find that the portable layer is using AT91F_AIC_ConfigureIt(), but I have #defined this to a macro in the header file, hence it does not use the library functions.

The library functions are unfortunately a bit IAR centric.  They use inline functions rather than macros.  You can define away the inline and create a load of functions, but this is not really a good solution.  If you can get the inline functions to work as inline functions you should have the optimised solution.  I believe there was a post some time back on this forum about how to do this.  You had to setup some #define to the correct ‘inline’ keyword, maybe __inline or something like that.

My preference is to use the inline functions as a guide, then implement my own equivalents, as I did with the AT91F_AIC_ConfigureIt().  This is fine provided you are not using too many of them.

Regards.

nobody wrote on Tuesday, June 06, 2006:

I see your point, but still : Should GCC not be able to optimese away unused code ?

I saw an another forum (can’t remember where) that the following Compiler flags should do the trick:
CFLAGS += -ffunction-sections
CFLAGS += -fdata-sections
CFLAGS += -Wl,–gc-sections
The linker file would have to edited afterwords. I could, however, not make it work.

Has anyone got any experience with this ?

/RaceMouse

nobody wrote on Wednesday, June 14, 2006:

The Linker script had to be edited:

<–snip–>
SECTIONS
{
    . = 0;
    .startup : {
        KEEP(*(.startup))
    }>flash

    .text :
<–!snip–>

and

*(.data) to *(.data.*)
*(.text) to *(.text.*)

The KEEP() directive did the trick. The OS is now running and uses ~3.7K Flash.

Thanks for the help :slight_smile: