[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] Re: Optimization - what is bad on this code ?

From: David Brown
Subject: [avr-gcc-list] Re: Optimization - what is bad on this code ?
Date: Mon, 05 Oct 2009 12:35:18 +0200
User-agent: Thunderbird (Windows/20090605)

Ruud Vlaming wrote:
On Monday 05 October 2009 09:53, David Brown wrote:

Ruud Vlaming wrote:
Give it a try.
Your explanation is correct (and the 8/16-bit issue explanation was particularly nice), but your advice at the end is not.
Although that is a matter of taste, this was meant in the sense that
Vaclav should try in order to check if i was correct, not that i meant
that the code is approved just because is works.

I would personally not code it this way because the intentions of the
code are not very obvious (why not make a loop that simply ends at zero?) although that is a matter of taste too.

Fair enough.

If you want icnt to be able to store "-1", so that "icnt + 1" is 0, then make icnt a "signed" value ("int", or for better efficiency, a "signed char" or "sint8_t"). Static type checking is limited enough in C - don't make it worse by deliberately lying to the compiler!
Let it be clear that making use of "overflows" in unsigned arithmetic
is perfectly valid and well defined C code, so he is not lying to the
compiler. If you do not believe me check the C99 standard for it.

I've just checked, and you're right - unsigned overflow is defined by the C standards so that "+" is really "plus modulo (UINT_MAX + 1)", and the value of "icnt" after decrementing from 0 is UINT_MAX (for an unsigned int). I guess it is then just a matter of taste - I dislike writing something that looks like you are setting an unsigned variable to -1, even though it is well-defined behaviour.

For signed types that is an entire different matter, and my advise is,
never rely on any specific behaviour. Since it is explicitly undefined
by the standard.


Also note that the optimiser may still assume that "icnt + 1" is always greater than 0, even with icnt changed "unsigned int".
I think this is incorrect, arithmetic on "unsigned int" is perfectly well defined, namely, it must be modulo one plus the largest number the type can represent. See my explanation above.

Again, you are right - my argument only applies to signed values.

The reason for this is that the "-fstrict-overflow" flag (enabled at -Os and above) tells the compiler that any overflows are undefined
This is only so for signed integers, and makes gcc comply with the standard. The flag has no influence on unsigned integers.

thus it knows that (with unsigned icnt) "icnt + 1" is either greater than icnt and at least as big as 1, or it is undefined and it can do what it wants. Therefore, it is never 0.
No, i don't agree. Again, unsigned int arithmetic is well defined
and as far as i know, gcc complies 100%. So you will not come
into a situation that gcc optimizes the body away for unclear

This behaviour can be modified by using the "-fwrapv" flag to tell the compiler that arithmetic uses twos-complement, and thus overflow is defined. But that flag needs to be specifically enabled.
Also this flag only applies to signed integers.

Thanks for correcting me here.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]