Critical loop containing many “if” whose output is

2020-07-17 16:08发布

I have a critical loop in my code with this shape :

int myloop(int a, .....){

   /* some stuff */

   // Critical loop
   while(...){
       /* Some Stuff */
       if(a == 1){
          // .....
       }
       else if(a == 2){
          // .....
       }
       else if(a == 3){
          // .....
       }
       else{
          // ....
       }
   }
}

As the loop never touches the value of "a" the branch taken will never change, but as this loop is really heavy it will require to test the value of "a" many times, which is totally unnecessary. The best thing is probably to duplicate the loop, so that the "if" can be tested before the loop begins, but this would mean copying a lot of stuff common to both situations and will result in a very ugly code...

Is there any way to ask GCC/G++ to duplicate this code when it compiles it ? Or any other trick to avoid testing the value so many times ?

Thank you for your help !

Nathann

10条回答
放我归山
2楼-- · 2020-07-17 16:39

How about defining a function that does whatever happens inside the while loop and define it inline? Then move your while loop inside each if and call the function there. That will do exactly what you want.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2020-07-17 16:45

I'd suggest to pass "a" as a template parameter, ie

template< int a > 
int myloop(.....) {
  if( a==1 ) { ... }
}

Like that it would be optimized away properly.

However, you won't be able to pass a variable as template parameter, so somewhere else you'd have to put that switch.

switch(a) { 
  case 1: myloop<1>(...); break;
  ...
}
查看更多
放我归山
4楼-- · 2020-07-17 16:46
int myloop(int a, ...){
    if(a == 1){
      myloop1(a, ...);
    }
    else if(a == 2){
      myloop2(a, ...);
    }
    else if(a == 3){
      myloop3(a, ...);
    }
    else{
      myloopelse(a, ...);
    }
}

myloop#(int a, ...){
    SomeStuffAboveLoop(...)
    while(...){
        SomeStuffInsideLoop(...)
        //Do what you want for the appropriate #
    }
}

You could change the if block to a switch as well, which many other answers show.

查看更多
Rolldiameter
5楼-- · 2020-07-17 16:47

you could also consider moving the loop inside the conditions something like the following. This sacrifices code size for runtime efficiency.

if (a == 0) {
    while (...) {
       /* some stuff */
       // 0 stuff
    }
} else if (a == 2) {
    while (...) {
       /* some stuff */
       // 2 stuff
    }
} else if (a == 3) {
 ....
}
查看更多
Explosion°爆炸
6楼-- · 2020-07-17 16:58

You can use switch statement:

while(...)
{
   switch(a)
   {
   case 1:
      // do what you want
      break;
   case 2:
      // do what you want
      break;
   case x:
      // do what you want
      break;
   default:
      //if not matching any previous..
   }
}
查看更多
再贱就再见
7楼-- · 2020-07-17 17:00

How about making each a separate function, and then have a pointer to the function?

void func_a() {
    // ...
}

void func_b() {
    // ...
}

int myloop(int a, ...) {
    void (*func)();
    if (a == 1) {
        func = &func_a;
    } else if (a == 2) {
        func = &func_b;
    } ...

    while (1) {
        /* Some stuff */
        func();
    }
}
查看更多
登录 后发表回答