I have two files:
#include <stdio.h>
static inline void print0() { printf("Zero"); }
static inline void print1() { printf("One"); }
static inline void print2() { printf("Two"); }
static inline void print3() { printf("Three"); }
static inline void print4() { printf("Four"); }
int main()
{
unsigned int input;
scanf("%u", &input);
switch (input)
{
case 0: print0(); break;
case 1: print1(); break;
case 2: print2(); break;
case 3: print3(); break;
case 4: print4(); break;
}
return 0;
}
and
#include <stdio.h>
static inline void print0() { printf("Zero"); }
static inline void print1() { printf("One"); }
static inline void print2() { printf("Two"); }
static inline void print3() { printf("Three"); }
static inline void print4() { printf("Four"); }
int main()
{
unsigned int input;
scanf("%u", &input);
static void (*jt[])() = { print0, print1, print2, print3, print4 };
jt[input]();
return 0;
}
I expected them to be compiled to almost identical assembly code. In both cases jump tables are generated, but the calls in the first file are represented by jmp
, while the calls in the second one by call
. Why doesn't compiler optimise call
s? Is is possible to hint gcc that I would like to see jmp
s instead of call
s?
Compiled with gcc -Wall -Winline -O3 -S -masm=intel
, GCC version 4.6.2. GCC 4.8.0 produces slightly less code, but the problem still persists.
UPD: Defining jt
as const void (* const jt[])() = { print0, print1, print2, print3, print4 };
and making the functions static const inline
didn't help: http://ideone.com/97SU0
Compiler writers have a lot of work to do. Obviously they prioritize the work that has the biggest and fastest payoff.
Switch statements are common in all kinds of code, so any optimizations performed on them will have an effect on lots of programs.
This code
jt[input]();
is a lot less common, and therefore a lot longer down on the compiler designers' TODO-list. Perhaps they haven't (yet) found it worth the effort to try to optimize it? Will that win them any known benchmarks? Or improve some widely used codebase?
Because the array of function pointers is mutable. The compiler has decided it can't assume the pointers won't be changed. You might find the assembly different for C++, and/or make jt const.
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