6

I have a switch statement in some time-critical code. I was trying to optimize it with __builtin_expect, but it does not seem to be working. I'm wondering if anyone can tell me if I'm missing some detail, or if the compiler simply does not optimize for it. I have tried the following on my host machine:

int main() {
    volatile int v=0;
    long i = 0;

    for (i=0; i<1000000000L; i++) {
            switch(__builtin_expect(v, EXPT)) {
            case 7:
                    v=7;
                    break;
            default:
                    v=7;
                    break;
            }
    }
    return v;
}

Then I compile and run as follows:

~/code/builtinexpect> gcc bie.c -o bie -D EXPT=0 && time ./bie 

real    0m2.092s  
user    0m2.086s
sys     0m0.000s
~/code/builtinexpect> gcc bie.c -o bie -D EXPT=7 && time ./bie 

real    0m2.092s
user    0m2.086s
sys     0m0.000s

I am using GCC version 4.5.1.

Zenexer
  • 18,788
  • 9
  • 71
  • 77
John
  • 3,400
  • 3
  • 31
  • 47

2 Answers2

6

GCC does not support this on any architecture I'm aware of. If you have a switch statement which strongly favors a particular case, your best recourse is to do an if ... else switch ... statement. This would result in the optimization you're looking for.

RandomDSdevel
  • 431
  • 6
  • 17
blackghost
  • 1,730
  • 11
  • 24
3

Both case branches (and therefore all cases) do the same thing, so the compiler is free to replace the whole switch statement with v=7. Even if it doesn't (without optimization), would you expect any real difference in timing?

But more to the point, __builtin_expect evaluates as (v == EXPT), either (0) or (1), so case 7: will never be taken.

Quuxplusone
  • 23,928
  • 8
  • 94
  • 159
Brett Hale
  • 21,653
  • 2
  • 61
  • 90
  • 1
    He didn't use compiler optimizations, so the code should differ and may cause forced mispredictions, but nice catch about the boolean-ness! – Leeor Feb 06 '14 at 19:45
  • 3
    @Leeor - I like to think a branch-predictor would get it mostly right with a billion iterations:) – Brett Hale Feb 06 '14 at 19:54
  • 1
    I would hope for a decent __builtin_expect to be strong enough to force the HW not to. Those HW folks need to know their place :) – Leeor Feb 06 '14 at 20:19
  • 1
    Thanks for the replies. I shaved down the example to post here to only two case statements (though I had tried it with more, with differing side-effects, but got the same results). The real-life scenerio is run millions of times per second, and even a 1% improvement would be significant. – John Feb 07 '14 at 14:05
  • 3
    According to [gcc documentation](http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html), "The return value is the value of exp, which should be an integral expression" (it says it _expects_ `exp == c`, but does not say it returns the result of this)... I just tried it, and case 1 and 0 are never hit if I initialize to -1. – John Feb 07 '14 at 14:14