The GCC trick on optimization for AVR32

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I just found out that if O3 is used as optimization level, then the compiler can optimize a function which has a constant assigned its input, and do static calculation on this and optimize away the useless code.

Example:

int spi_initMaster(volatile avr32_spi_t *spi, const spi_options_t *options)
{
  u_avr32_spi_mr_t u_avr32_spi_mr;

  if (options->fdiv > 1 ||
      options->modfdis > 1) {
    return SPI_ERROR_ARGUMENT;
  }

  // Reset.
  spi->cr = AVR32_SPI_CR_SWRST_MASK;

  // Master Mode.
  u_avr32_spi_mr.mr = spi->mr;
  u_avr32_spi_mr.MR.mstr = 1;
  u_avr32_spi_mr.MR.fdiv = options->fdiv;
  u_avr32_spi_mr.MR.modfdis = options->modfdis;
  u_avr32_spi_mr.MR.llb = 0;
  u_avr32_spi_mr.MR.pcs = (1 << AVR32_SPI_MR_PCS_SIZE) - 1;
  spi->mr = u_avr32_spi_mr.mr;

  return SPI_OK;
}

The code

Quote:

if (options->fdiv > 1 ||
options->modfdis > 1) {
return SPI_ERROR_ARGUMENT;
}

will not appear in the compiled program if the values checked as constant.

And I also found out that if the values are outside the limits, then compiler would completely delete this function, because it got return with SPI_ERROR_ARGUMENT and it's useless to other program.

This is a great stuff!!! This is what I dreamed of in AVRGCC, now I can do the static assertion for all the hardware limited parameters!

Cheng

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You'll find plenty of other useful tips here:
http://atmel.com/dyn/resources/p...

-sma

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok, thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

now I'm wondering how to let compiler give me a error if a device driver function is been deleted due to its out of range parameter.

Anyone have ideas?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Maybe something along the lines of the BUILD_BUG_ON() macro from the Linux kernel?

/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))

The error message when it triggers isn't exactly pretty and helpful, but it does cause the build to fail.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thanks, I will try this macro.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

it seems this BUILD_BUG_ON is not working for me.

I tried it with a function call with an out of range argument input, and check if the function return invalid argument indication value, and the compiler didn't have any error or warning with it.

BTW, my optimization level is O3.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

anyone have good static assertion methods to check if a function gets invalid argument?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've always just stolen the BUILD_BUG_ON from Linux too. So can you actually just stick BUILD_BUG_ON(1) in your source and it still compiles? How are you using it where it doesn't work as expected?

-S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if it's BUILD_BUG_ON(1), then compiler will give error. but if it's a variable which hold a function returned value, then the compiler never stop.

But now the AVR32 GCC can do the constant function parameter preprocess, then there must be a way to check for the function return value, right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Depends on the order in which GCC runs it's internals I 'spose. If it runs the error checking BUILD_BUG_ON depends on too late in the process then it may have lost track of where the error came from. As such it probably runs the error checking quite early, maybe before the function call evaluates to a constant.

I'd actually use the BUILD_BUG_ON in the invalid argument check in the function. eg, if it can't take numbers greater than 5 or less than 0 just put a BUILD_BUG_ON at the top of the function

BUILD_BUG_ON(arg > 5 || arg < 0)

-S.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ok, I will try this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

no, it doesn't work.

I have put the BUILD_BUG_ON() at the top of the function, and I called this function in main() with a out of range argument but the compiler didn't say anything.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

anyone has idea?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, BUILD_BUG_ON is for errors that you can always detect at compile time. That's generally not going to be the case with function parameters...

The optimizations you seem to want are constant propagation ones. Declare your functions static, and depending on various things you may get the optimization you want as part of inlining.