1

I'm using avr-gcc on a 16-bit target platform

I'd like to do something like this:

#define F_CPU 16000000
#define MIN_UPDATES_PER_REV 100
#define MAX_RPM 10000
#define UPDATE_PERIOD_cy ( F_CPU*60 / (MIN_UPDATES_PER_REV*MAX_RPM) )

As expected, I get an overflow error because MIN_UPDATES_PER_REV*MAX_RPM evaluates to 0xf4240:

bldc.h:9:40: warning: integer overflow in expression [-Woverflow]
#define UPDATE_PERIOD_cy ( F_CPU*60 / (MIN_UPDATES_PER_REV*MAX_RPM) )
                                                          ^

Things work out if I force the constants to 32 bits and convert back to uint16_t after folding, although I lose the benefits of -Woverflow:

#define UPDATE_PERIOD_cy (uint16_t)( (uint32_t)F_CPU*60 / ((uint32_t)MIN_UPDATES_PER_REV*MAX_RPM) ))

Can I force gcc to handle large intermediate values during constant folding?

Can I force the preprocessor to do constant folding for me?

Are there best practices I should know about?

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
fkoran
  • 191
  • 6
  • Do you know who provides this compiler? Have you tried to ask them for a fix? – ddbug Sep 25 '16 at 00:43
  • The compiler is behaving correctly. I'm hoping to find a way to make it behave in a way that's incorrect but slightly more convenient. – fkoran Sep 25 '16 at 02:23

2 Answers2

2

You can specify the size of constants by adding a suffix to them, like 100UL or 100LL.

Another way to solve your immediate problem is to re-order the expression:

#define UPDATE_PERIOD_cy ( F_CPU*60 / MIN_UPDATES_PER_REV / MAX_RPM) )

This will give the same result, but avoids the large intermediate which overflows.

UncleO
  • 8,299
  • 21
  • 29
0

Can I force gcc to handle large intermediate values during constant folding?

No you cannot do this. General C rules are always applied. Meaning MIN_UPDATES_PER_REV will be evaluated to uint16 and MAX_RPM to uint8. The result of multiplication doesn't fit into uint16and you get the -Woverflow.

Can I force the preprocessor to do constant folding for me?

The preprocessor only does the macro substitution and GCC does the constant folding. If the question is about forcing GCC to do the constant folding, no you cannot but GCC will do the constant folding even without optimization flag.

Are there best practices I should know about?

This is a subjective question. (I think you already use best way to do with casting. As it is optimized at compile time, you do not have an execution overcost).

Julien
  • 1,810
  • 1
  • 16
  • 34