Suppose I have N different integral values known at compile time, V_1 through V_N. Consider the following structures:
const int x = foo();
switch(x) {
case V_1: { /* commands for V_1 which don't change x */ } break;
case V_2: { /* commands for V_1 which don't change x */ } break;
/* ... */
case V_N: { /* commands for V_1 which don't change x */ } break;
}
versus
const int x = foo();
if (x == V_1) { /* commands for V_1 which don't change x */ }
else if (x == V_2) { /* commands for V_2 which don't change x */ }
else ...
else if (x == V_N) { /* commands for V_N which don't change x */ }
Do modern C++ compilers treat these differently? That is, do they apply different potential optimization to these code structures? Or do they "canonicalize" them to the same for, then decide on optimizations (such as whether to form a jump table or not)?
Notes:
-O3
for clang and GCC)switch
es and if-then-else
-chains is the same in some optimization levels and different in others, that's also interesting.N
- give thresholds if possible.As it turns out, the switch statement is faster in most cases when compared to if-else , but significantly faster only when the number of conditions is large. The primary difference in performance between the two is that the incremental cost of an additional condition is larger for if-else than it is for switch .
Compiler optimization is generally implemented using a sequence of optimizing transformations, algorithms which take a program and transform it to produce a semantically equivalent output program that uses fewer resources or executes faster.
Speed: A switch statement might prove to be faster than ifs provided number of cases are good. If there are only few cases, it might not effect the speed in any case. Prefer switch if the number of cases are more than 5 otherwise, you may use if-else too.
The results show that the switch statement is faster to execute than the if-else-if ladder. This is due to the compiler's ability to optimise the switch statement. In the case of the if-else-if ladder, the code must process each if statement in the order determined by the programmer.
Ironically, that is exactly the test I did just a couple of days back for most recent compilers. As it happened, with latest compilers, clang
produces the same assembly for switch
and if
- for small number of cases (below 5) it produces a bunch of direct conditional jumps, while for 5 or more cases it does an indirect table jump.
On the other hand, gcc
treats those differently: it converts switch
to indirect table jump, while a series of if
statements remain a series of conditional direct jumps.
It is also worth noting, that if switch case has "holes" in it (i.e. possible values for control variable which are not covered by case label), it can be still converted into series of conditional direct jumps or indirect table jump, but I wasn't able to figure out the exact formula.
Here is some play code: https://gcc.godbolt.org/z/Lll1Kd
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With