Is the Arduino compiler very bad at optimizing code ?

I wonder because I often get the message that sketch is to big (Leonardo board). I have found out that I can’t use a TFT touch shield
http://dx.com/p/2-8-tft-lcd-touch-shield-module-for-arduino-silver-blue-black-223437#.UwNoPyf0ywI
because not very much can be put in the Leonardo. Is the reason for this the compiler being bad at optimization ?
Example of my latest fairly short code. It compiles with message
Sketch too big;34822 bytes (of a 28672 byte maximum)

#include <SdVolume.h>
#include <SdStream.h>
#include <SdInfo.h>
#include <SdFile.h>
#include <SdFatUtil.h>
#include <SdFatStructs.h>
#include <SdFatmainpage.h>
#include <SdFatConfig.h>
#include <SdFat.h>
#include <SdBaseFile.h>
#include <Sd2Card.h>
#include <ostream.h>
#include <MinimumSerial.h>
#include <istream.h>
#include <iostream.h>
#include <ios.h>
#include <bufstream.h>
#include <ArduinoStream.h>
#include <UTouchCD.h>
#include <UTouch.h>
#include <UTFT.h>
#include <memorysaver.h>

// Declare which fonts we will be using
extern uint8_t BigFont[];

UTFT        myGLCD(ITDB24D,23,22,21,20);   // Remember to change the model parameter to suit your display module!
UTouch      myTouch(19,17,18,8,9);
SdFat		sd;
SdFile		myFile;

int x, y;

void waitForIt(int x1, int y1, int x2, int y2)
{
	myGLCD.setColor(255, 0, 0);
	myGLCD.drawRoundRect (x1, y1, x2, y2);
	while (myTouch.dataAvailable())
	myTouch.read();
	myGLCD.setColor(255, 255, 255);
	myGLCD.drawRoundRect (x1, y1, x2, y2);
}

void drawButtons()
{
	// Draw the lower row of buttons
	myGLCD.setColor(0, 0, 255);
	myGLCD.fillRoundRect (160, 130, 300, 180);
	myGLCD.setColor(255, 255, 255);
	myGLCD.drawRoundRect (160, 130, 300, 180);
	myGLCD.print("Enter", 190, 147);
	myGLCD.setBackColor (0, 0, 0);
}


void setup()
{
  /* add setup code here */
  myGLCD.InitLCD(1);
  myGLCD.clrScr();

  myTouch.InitTouch(LANDSCAPE);
  myTouch.setPrecision(PREC_LOW);

  myGLCD.setFont(BigFont);
  myGLCD.setBackColor(0, 0, 255);
  if (!sd.begin(17, SPI_HALF_SPEED))
	sd.initErrorHalt();
  // open the file for write at end like the Native SD library
  if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END))
	sd.errorHalt("opening write failed");
  drawButtons();
}

void loop()
{
  /* add main program code here */
  while (true)
  {
	  if (myTouch.dataAvailable())
	  {
		  myTouch.read();
		  x=myTouch.getX();
		  y=myTouch.getY();
		  if ((y>=130) && (y<=180))  // Third row
		  {
			  if ((x>=160) && (x<=300))  // Button: Enter
			  {
				  waitForIt(160, 130, 300, 180);
				  myGLCD.setColor(0, 0, 0);
				  myGLCD.fillRect(0, 208, 319, 239);
				  myGLCD.setColor(0, 255, 0);
			  }
		}
	  }
  }
}

fairly short code.

And the 50 libraries you are including, what about them?


Rob

Graynomad:

fairly short code.

And the 50 libraries you are including, what about them?


Rob

Most of them relate to SD card function. I tried removing all but SDfile and SDfat and it didn't make any difference in code size.

extern uint8_t BigFont[];

That looks like a candidate for PROGMEM.

The UTFT and Utouch libraries take up quite a bit of memory. I assume you have edited the memorysaver.h file as explained in the documentation of the UTFT library? I was using a 5" inch touchscreen TFT (800x480px) with an Arduino Mega and switched to a Due for the extra speed/memory.

AWOL: extern uint8_t BigFont[];

That looks like a candidate for PROGMEM.

Do you mean that this is going to be placed in the program (flash) memory ? Are there a better way here ?

Actually, gcc is very good at optimization. But it optimizes for speed and performance which sometimes makes code bigger.

(For example, inlining code can save the overhead of a function call at the expense of code size.)

KeithRB: Actually, gcc is very good at optimization. But it optimizes for speed and performance which sometimes makes code bigger.

(For example, inlining code can save the overhead of a function call at the expense of code size.)

Is it not possible to tell it to optimize for size instead ?

No, the gcc optimization flags are "baked in" to the IDE.

KeithRB:
No, the gcc optimization flags are “baked in” to the IDE.

Not in IDE 1.5x

For the AVR look in:
{installdir}/hardware/arduino/avr/platforms.txt

These variables control it for C++ and C
compiler.cpp.flags
compiler.c.flags

You can set any gcc option you like.

— bill

bperrybap:

KeithRB: No, the gcc optimization flags are "baked in" to the IDE.

Not in IDE 1.5x

For the AVR look in: {installdir}/hardware/arduino/avr/platforms.txt

These variables control it for C++ and C compiler.cpp.flags compiler.c.flags

You can set any gcc option you like.

--- bill

I might point out that I'm using Visual Micro with Atmel Studio and have Arduino IDE 1.05 installed. So going to IDE 1.5 could be a solution to my problem ?!

jfri: I might point out that I'm using Visual Micro with Atmel Studio and have Arduino IDE 1.05 installed. So going to IDE 1.5 could be a solution to my problem ?!

I wouldn't think so. The hard coded compiler commandline options are inside of the Arduino IDE (pre 1.5) but it sounds like you aren't using the Arduino IDE so I'm not seeing how swapping out the Arduino IDE would help.

Seems like you should be able to just go in and modify the scripts or Makefiles that are being used for your environment to change the compiler options.

--- bill

bperrybap:

jfri: I might point out that I'm using Visual Micro with Atmel Studio and have Arduino IDE 1.05 installed. So going to IDE 1.5 could be a solution to my problem ?!

I wouldn't think so. The hard coded compiler commandline options are inside of the Arduino IDE (pre 1.5) but it sounds like you aren't using the Arduino IDE so I'm not seeing how swapping out the Arduino IDE would help.

Seems like you should be able to just go in and modify the scripts or Makefiles that are being used for your environment to change the compiler options.

--- bill

Actually I think that Visual Micro is calling the Arduino IDE in some way. For example I have been told that I should expect exactly the same compile result as in the Arduino IDE. In Atmel Studio there are options for compiler optimization for size or speed. This settings does not affect my code size with as much as a single byte. I think it's because Visula Micro uses the Arduino IDE settings.

jfri:
This settings does not affect my code size with as much as a single byte.

In general, with AVR processors, the two are the same. Smaller code = faster code. It’s not surprising the switch has little to no effect.

The most effective optimization tool is between your ears. Use some of the GCC dump tools to determine which modules are causing you the most grief and then come up with a plan to reduce / eliminate those modules.

In general, with AVR processors, the two are the same. Smaller code = faster cod

That's not necessarily the case; smaller code may have loops, and loops have overheads. If you unroll the loops, you get larger, but quicker code.

From the verbose compiler output: avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p . The compiler is already optimizing for size, -Os.

tf68: From the verbose compiler output: avr-gcc -Os -Wl,--gc-sections -mmcu=atmega328p . The compiler is already optimizing for size, -Os.

Then it's not very good at it. An opinion that I also got confirmed at the Visual Micro support forum. I wonder if I have gained anything in this regard compared to Microchips free C compilers for PIC. Their free version offer no optimization and registered license can produce about 40% smaller code. Btw this was one of the reason for me to look at other alternatives like Arduino.

jfri: Then it's not very good at it.

It's all open source. If you believe it's flawed then stop winging and do something about it.

Btw this was one of the reason for me to look at other alternatives like Arduino.

Just a thought but Atmel does make AVR processors with significantly more memory that are not much more expensive. There are even Arduino boards selling today that use some of those "bigger" processors.

My experience over the past 4-5 years with the AVR is that avr-gcc is very good at optimizations.

I've been doing embedded work for more than 30 years and have used many different C environments and have watched the optimizers advance over the decades. Todays gcc optimizations are pretty incredible compared to what was done 30 years ago or when the early gcc versions came out in the late 80's.

Before slamming the compiler optimizer you should first make sure that there is not dead code being linked in. There are many Arduino libraries that depend on using -ffunction-sections and -fdata-sections to weed out code that they asked to be linked in but then never used. In order to use these, it isn't just options to the compiler you also have to use some flags to the linker. Pulling in "dead wood" code is not a compiler optimization problem but rather a library and sketch author issue with respect to how the modules are constructed and the actual library-archives are built. Todays gcc and linker can work now around these author/programmer/library-archive in-efficiencies as long as the appropriate options used.

I'd build your image with the Arduino IDE first just to make sure that these linker optimizations are being done as it sets the compiler and linker options to do this. Then after that I'd go take a look at the actual code/link map and see what is eating up the space. You may be surprised to see what is being pulled in. Often times when I've seen unexpectedly large code it is because of something that either shouldn't have been linked in or something that I went "oh yeah" I forgot about that, and that piece/component is quite large.

Then after you have verified that there isn't anything obviously silly going on, with respect to pulling in code that shouldn't be pulled in, go look at some example code and see what machine code the compiler generates vs what you would have done by hand.

From my looking at avr-gcc output over the past 4-5 years I've not seen too many cases where the compiler generated poor code. Sometimes you do have to massage the C/C++ source code to get super efficient code because of the AVR really being an 8 bit processor and that can make a big difference, but that isn't really a compiler optimizer issue either.

I'd be curious to see an example of some specific code that you think the compiler did a poor job on code generation.

--- bill

bperrybap:
Before slamming the compiler optimizer you should first make sure that there is not dead code being linked in.
There are many Arduino libraries that depend on using -ffunction-sections and -fdata-sections to weed
out code that they asked to be linked in but then never used.
In order to use these, it isn’t just options to the compiler you also have to use some flags to the linker.
Pulling in “dead wood” code is not a compiler optimization problem but rather a library and sketch author issue

I’d build your image with the Arduino IDE first just to make sure that these linker optimizations are being done as it
sets the compiler and linker options to do this.
Then after that I’d go take a look at the actual code/link map and see what is eating up the space.
You may be surprised to see what is being pulled in.

I’d be curious to see an example of some specific code that you think the compiler did
a poor job on code generation.

— bill

As an example I list a short program below. For the Arduino IDE it results in a 22774 byte size which seem much to me.
But I should point out that it’s possible that using a TFT display is such a complex task that the code
inevitable grows to a significant size.
Part of build message is
C:\Arduino\hardware\tools\avr\bin\avr-g++ -c -g -Os -Wall -fno-exceptions -ffunction-sections -fdata-sections -mmcu=atmega32u4 -DF_CPU=16000000L -MMD -DUSB_VID=0x2341
so those part wich you mentioned are taking care of.

#include <UTFT.h>
#include <memorysaver.h>

// Declare which fonts we will be using
extern	    uint8_t BigFont[];

UTFT        myGLCD(ITDB24D,23,22,21,20);   // Remember to change the model parameter to suit your display module!

void setup()
{
	/* add setup code here */
	myGLCD.InitLCD(LANDSCAPE);
	myGLCD.clrScr();
	myGLCD.setFont(BigFont);
	myGLCD.setBackColor(255, 255, 255);
}

void loop()
{
    long	x;
	
    for (x=0; x<5; x++)
    {
	    myGLCD.setColor(0, 0, 0);
	    myGLCD.fillRoundRect (10+(x*60), 10, 60+(x*60), 60);
	    myGLCD.setColor(255, 255, 255);
	    myGLCD.drawRoundRect (10+(x*60), 10, 60+(x*60), 60);
	    myGLCD.printNumI(x+1, 27+(x*60), 27);
    }
    do {} while(true);
}