[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 2.0.0.22 (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.
Agreed.
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
reasons.
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.
Ruud.