Using goto pointers will likely result in slower code because it shuts off some of gcc's other optimizations (or would the last time I read up on it). Gcc essentially decides that it could be way too complicated to try to keep up with what might be going on and assumes that many more branch instructions can target every goto label that has been && than is really the case. If you insist on trying to use this method I suggest that you attempt to use an integer and another switch/case rather than the goto. Gcc will like be able to make sense of that.
Aside from that, for many statements this may not be worth the work or it may actually work better the way it is. It really does depend a lot on what stmt
actually is.
Refactoring stmt
into a static
function will likely yield good results if stmt
is indeed expensive or big code.
Another thing you might try if you can would be to hoist stmt
out of the switch/case and just execute always execute it. Sometimes this is the cheapest way to go, but that really does depend on what stmt
actually does.
Another thing you might do is refactor all of stmt
, do_stmt_related2A
, and do_stmt_related2A
all into file static
functions, like this:
// args in this is just a psudocode place holder for whatever arguments are needed, and
// not valide C code.
static void stmt_f(void (*continuation)(arg_list), args) {
stmt; // This corresponds almost exactly to stmt in your code
continuation(args);
}
static void do_stmt_related2A_f(args) {
do_stmt_related2A;
}
static void do_stmp_related2B_f(args) {
do_stmt_related2B;
}
...
switch (condition) {
case A:
stmt_f(do_stmt_related2A_f, args);
break;
case B:
...
The call to the continuation function at the end of stmt_f is a tail call and will most likely become a jump rather than a real call. Because all of these are static it is possible that the compiler would see the entire set of values which could be continuation functions and optimize some more, but I don't know that.
Unless stmt is very big it is very likely that this is a micro-optimization that just isn't worth it. If you really want to know then you should compile to assembly and try to see what the compiler really does with your original code. It may very well do a better job than you think on it.
Oh, one last thing you might try is if you control what actual values A, B, C.. can take then you could make sure that the ones with similar prefixes have adjacent values. If A and B really are next to each other and if the compiler decides that it needs to break up the switch/case into a few different jump tables then it will likely put A and B in the same jump table and also see that they have the same prefix and hoist that code out for you. This is more likely if C, which does not share that prefix, is not adjacent to A or B, but then your overall code could be worse.