[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-gcc-list] Re: How to use inversion in if() - might be a bug rep
From: |
David Brown |
Subject: |
Re: [avr-gcc-list] Re: How to use inversion in if() - might be a bug report ? |
Date: |
Tue, 01 Sep 2009 17:07:52 +0200 |
User-agent: |
Thunderbird 2.0.0.22 (Windows/20090605) |
Vaclav Peroutka wrote:
> David,
>
(Try to remember to post back to the list, rather than individual users,
unless it is specifically an off-list email.)
>> The "bug" is in your code (alternatively, it is in the C standards!).
>> This is the way C works - before any arithmetic or logical operation,
>> and on various other occasions (such as in a if(), while() or switch()
>> test), any data unit smaller than an int gets promoted to an int. That
> OK, I did not know that it is in C standard.
>
Now you know!
For the future, it's polite to word your posts with the assumption that
/you/ have got it wrong, rather than implying the compiler (or library,
or other tools) are at fault. The tools do have a few bugs, but user
error is more common.
>> means the "~" complement is done as a 16-bit int. avrgcc is pretty
>> good (not perfect, but not bad) at removing unnecessary 16-bit code
>> when it doesn't affect the results of the operation. In this case,
>> however, the 16-bit promotion /does/ affect the working of the code,
>> and it must be kept there.
> From this point of view, if I have "if (++someUCharVariable) {}", the
> result should be always true ? 0xff will be promoted to 0x00ff,
> increased to 0x0100. But this will not happen in avr-gcc (at least in my
> version). The ASM looks like this:
> if (++someUCharVariable) {
> e2: 80 91 60 00 lds r24, 0x0060
> e6: 8f 5f subi r24, 0xFF ; 255
> e8: 80 93 60 00 sts 0x0060, r24
> ec: 80 91 60 00 lds r24, 0x0060
> f0: 88 23 and r24, r24
> f2: 91 f2 breq .-92 ; 0x98 <main+0x18>
> which is correct from 8-bit view, but not from ANSI/ISO standard ? No
> 16-bit expansion ?
>
No, what happens is that the operation ++someUCharVariable is carried
out as 8-bit. Then the result (0x00, after the overflow) is promoted to
16-bit and tested. The compiler avoids generating the 16-bit
instructions here, since the results are the same.
>> Without knowing the compiler flags you used, it's difficult to tell.
>> However, in general later avr-gcc versions often generate larger code
>> because they do more aggressive inlining. There are compiler flags
>> that counter this behaviour if you want to reduce code size - search
>> in the archives of this mailing list for examples.
> The new flag you probably have on mind is "-fno-inline-small-functions".
Other useful flags include "-fno-split-wide-types" and "--param
inline-call-cost=3" (as well as -Os, of course). Results vary by
application - sometimes inlining small functions makes code
significantly smaller, sometimes significantly bigger.
Using --combine and -fwhole-program can often help too.
> It does not however exist in older GCC 3.4.6. I would propose some
> clever mechanism, which counts number of calls of small functions and
> compares them with length of the function code. Then avr-gcc would make
> a decision if it is better to inline the function or not. But I am not
> compiler programmer. So I don't know if it is even possible.
>
I think that is exactly what the "--param inline-call-cost=3" flag does.
However, there are complications that make it difficult for the
compiler to get accurate function code lengths and inlining costs at an
early enough stage, so there will always be a need for some manual
tuning for space-critical code. I expect, however, that at some point
the standard configuration for avr-gcc will be changed to have flags set
to give a bit smaller code by default.
> Thank you for your explanation,
> Vaclav
>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [avr-gcc-list] Re: How to use inversion in if() - might be a bug report ?,
David Brown <=