Sign in to follow this  
Followers 0
jeb

optimization of code : without swtich, if, etc.

16 posts in this topic

hello,

i have several "modes" in a global  variable :

unsigned char mode;

and the value of "mode" is changed by pressing some buttons.

I have :

function Tick()

{

  switch (mode)

  {  case 1 :  Function1 (); break;

    case 2 :  Function2 (); break;

    case 3 :  Function3 (); break;

...} }

aren't these tests (with if, switch, etc.) every times Tick is called (so very often !!)

a waste of time ?

is it possible to do pointers to functions ?

example :

pointer ...    mode_functionptr;

whose value is changed when the button is pressed.

with then :

function Tick ()

{

mode_functionptr();        //without tests!

}

/////////////////

just another small question :

how to do a "switch/case" on two variables ?

is :

switch(i,j)

{

case (1,0) : ...

case (2,1) : ...

...

}

possible ?

thanx in advance !

Share this post


Link to post
Share on other sites

Hi jeb,

The pointers would be even slower than the switch statement :( For realtime stuff like clock ticks, I suggest taking a leaf out of TK's book... You have a counter which is incremented when the clock ticks, and then in the user_tick, you test that counter, and if it is not zero, you call your function. Your switch statement is bang-on though.

I'll leave the double-switch thingy to one of the C gurus :)

Share this post


Link to post
Share on other sites

hello

> The pointers would be even slower than the switch statement

that's not possible : the pointer to the function is *changed* only when a button

is pressed  (so in the call of DIN_NotifyToggle), so not so often at all !

the pointer would replace a

//

switch (mode)

case 1 : Function1();

...

//

by a

//

Functionptr();

//

where Functionptr points to Function1, Function2, or Function3.

is this possible in C ?

how to do a pointer to a function with SDCC ?

Share this post


Link to post
Share on other sites

Hello Jeb,

I'm ~99% sure that the dual switch stuff is not allowed.

You could for example put a switch block or "if/else if/.../else" into a case of a switch.

Another way is for example to create a 16-bits value "tmp" out of the two 8-bits values "i" and "j" and then to the case stuff on tmp:

uint16 tmp;
uint8 i, j;

tmp = (((uint16)i) << 8) + j;

case 0x0100:   //-> corresponding to i = 1, j = 0
...
case 0x0201:   //-> corresponding to i = 2, j = 1

On an 8-bit processor, it will certainly be cycle and memory consuming so if i and j are in the range of [0 ... 15] then you could even code the combination on one byte by doing only a shift of 4 on i. This would be much better. Actually any combination which would lead to a tmp coded on 8 bits would be better.

Best regards,

Lall

Share this post


Link to post
Share on other sites

Yeah, dual switching isn't a feature in C.  You can get the same effect by layering your switch statements

switch(j) {

case 1:

  switch(i) {

      case 0:

        // corresponds to j == 1 and i == 0

  }

}

Share this post


Link to post
Share on other sites

Thanx Lall !

The idea with << for the double switch is great !!!!!!    My second value is only 0 or 1 so (<<  1) is enough !

between :

switch ((i<<1) + j);

{  case 0x010:  //-> corresponding to i = 1, j = 0

    case 0x011:  //-> corresponding to i = 1, j = 1

    ...

    case 0x031:  //-> corresponding to i = 3, j = 1

}

and

switch (i) {

case 1: if j then ..... else ....

case 2: if j then ..... else ...

...}

which is better in terme of time consume ?

thanx

Share this post


Link to post
Share on other sites

Well if one of the value is only 0 or 1 then I believe the following would be the best:

if (j == 0)
{
  switch (i)
  {
     case 0: ...
     case 1: ...
     ...
  }
}
else
{
  switch (i)
  {
     case 0: ...
     case 1: ...
     ...
  }
}

Best regards,

Lall

Share this post


Link to post
Share on other sites

that's not possible : the pointer to the function is *changed* only when a button

is pressed  (so in the call of DIN_NotifyToggle), so not so often at all !

Give it a shot, but when I tested pointers last week, I found that it recalculated the pointer every time it used it :( Weird, I know....

Share this post


Link to post
Share on other sites

The second option would be faster.

Err maybe not....Putting the if statement on every case is going to kill sdcc's optimiser, it won't generate a jumptable that way :(

Share this post


Link to post
Share on other sites

This is probably way too late...

In old C compilers (I can't talk much for SDDC), switch statements are converted to jump tables, which run much faster then if/else statements or function invocations. I'm not great at explaining things, but wikipedia should help.

http://en.wikipedia.org/wiki/Jump_table (The example is actually for a PIC!)

So to answer your question, use a switch statement. Calling a function is "better" style, but if you want efficiency, you'll need to "inline" the function body in the switch statement.

Share this post


Link to post
Share on other sites

Welcome aboard!

This is probably way too late...

About four months late... and I think that was all said in the previous posts ;D But you're correct!

So to answer your question, use a switch statement. Calling a function is "better" style, but if you want efficiency, you'll need to "inline" the function body in the switch statement.

Maybe sometimes true but not in the case of SDCC. When you inline the function, the switch statement compiles entirely differently, and it kills the efficiency. It's better to call the function from the switch statement - and I mean call a function, not using a function pointer.

Just to add something interesting to my post... The jumptable generated by a simplified switch/case statement is generally faster than a series of 'if's , but there is some code that is always present for the jumptable, so if you only have a few options, or if you won't be using 'break' at the end of each case, sometimes the 'if' is actually faster. Sometimes.....

Share this post


Link to post
Share on other sites

Hi, I hope you all read the article at "How to Implement Branch Tables in C" at the end of the wikipedia page. It is very interesting. He advocates the use of function pointers, without switch at all but a real function table. It has pros and cons he well analyzes, and in the embedded world BTW.

Best regards. Didier.

Share this post


Link to post
Share on other sites

Nah I just tried it and analysed the output :) I've read about 1/4 of that document so far and he has already mentioned some of the things I've posted about above, for EG:

Maybe sometimes true but not in the case of SDCC. When you inline the function, the switch statement compiles entirely differently, and it kills the efficiency.

A quick survey of the documentation for a number of compilers revealed some interesting variations. They all claimed to potentially perform conversion of a switch statement into a jump table. However, the criteria for doing so varied considerably.

In the case where one has, say, 26 contiguous indices, each associated with a single function call (such as the example above), the compiler will almost certainly generate a jump table. However, what about the case where you have 26 non-contiguous indices, that vary in value from 0 to 1000?

What I've found so far was that SDCC would compile very heavy ASM if the code was not just-so. The only solid recommendation that can really be made here, is to try stuff out and see how you go... What I tried, and what was mentioned in that article (pointers to ram not rom), differ somewhat... But I can tell you that when I started to head in the direction suggested there, the code size exploded.

Share this post


Link to post
Share on other sites
aren't these tests (with if, switch, etc.) every times Tick is called (so very often !!)

a waste of time ?

no. It's dependend what your functions are doing at several cases.

PIC is fast enough...

is it possible to do pointers to functions ?

it will increase your application size and you have to add tk's scss library. It will increase the size too.

how to do a "switch/case" on two variables ?

you can use nested switch directives too. But one thing i noticed on my tests, that switch will increase your application size instead if/else terms.

so for little queries (with only some case) use if/else instead switch.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0