avr-gcc-list
[Top][All Lists]
Advanced

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

[avr-gcc-list] Re: C vs. assembly performance


From: David Brown
Subject: [avr-gcc-list] Re: C vs. assembly performance
Date: Sun, 01 Mar 2009 14:37:57 +0100
User-agent: Thunderbird 2.0.0.19 (Windows/20081209)

Vincent Trouilliez wrote:
On Sat, 28 Feb 2009 19:24:38 -0700 "Weddington, Eric"
<address@hidden> wrote:
You wouldn't need *nested* ifs, but an if-else-if structure, or
better yet, a table of function pointers, also known as a dispatch
table. Each method depends on the type of data that you're
switching on.

I switch on an unsigned byte, with contiguous values (0-24). A
Function table sounds elegant to my ear, but it would mean 25 functions ! In my case the work is done in-situ, within the switch statement, as it's takes only 2 or 3 statements to process a givne "case". Using functions would be both overkill and overwhelming to manage I think !! ;-)

I pasted my switch statement below for the curious.


These sorts of decisions depend very much on the circumstances. I am not nearly as anti-switch as Eric - I would use a switch in this case. I agree with him that many switches could be better expressed as if-trees or function tables (though the compiler can often do a better job at optimising switches than function tables...).

As Eric says, if's give you better control of your timing and priority, in case that is useful.

An interesting structure for replacing switches is a binary if tree:

// switch (x) for x = 0 .. 7
if (!(x & 0x04)) {
        if (!(x & 0x02)) {
                if (!(x & 0x01)) {
                        // case 0: ...
                } else {
                        // case 1: ....
                }
        } else {
                if (!(x & 0x01)) {
                        // case 2: ...
                } else {
                        // case 3: ....
                }
        }
} else {
        ...
}

This lets you avoid the long delays you get with a flatter if structure if you have lots of cases. Unfortunately, this doesn't seem to generate good code according to my very brief testing - ideally, we should see a series of "sbrs" or "sbrc" instructions, but in practice C's irritating int-promotion "feature" is getting in the way.


Apart from that, I've a couple of other comments on your code. The variable names "tmp16", "tmp32" and "tmpS16" are truly awful. It is also (usually) best to declare such temporaries in as small a block as possible. Thus they should not be at the start of the function, but instead make your cases like this:

{// (N * 0.75) - 40     DB41            -40 to +150 °C
        int16_t temp = (int16_t)(KLineFrameM1[41]) * 3 / 4 - 40;
        var_format_S16(buff, temp, 0);
        break;
}
        
That will give clearer code and let the optimiser be more flexible in its register choices.

Also avoid local automatic constant arrays (like "Yes" in your example) - they must be built on the stack each time the function is called, whether they are used or not. By making these "static", they will have local names but be built once at the start of the program. If you are short on ram space, you might also want to make them PROGMEM.





reply via email to

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