17

Say I have a function that takes a function pointer:

int funct(double (*f)(double));

And I pass it a function that doesn't actually do anything:

double g(double a) { return 1.0;}
//...
funct(g);

Will the compiler optimize out the calls to g? Or will this still have overhead? If it does have overhead, how much? Enough that it is worth overloading the function to receive both function pointers and constant values?

0

3 Answers 3

18

Newer versions of GCC (4.4 and later) can inline and optimize a known function pointer using the option -findirect-inlining. This only works when GCC also knows all of the code that uses the pointer.

For example, the C library function qsort will not benefit from this optimization. The compiled machine code for qsort is in the library, it expects a function pointer and the compiler cannot change that.

However, if you had your own implementation of qsort and you placed it in a header file or you used the very new GCC link-time optimization features, then GCC would be able to take your calling code, the function pointed to, and your qsort source and compile it all together, optimized for your data types and your comparison function.

Now, the only times that this really matters is when the function call overhead is much larger than the function itself. In your example of a function that does nothing much, using a function pointer is serious overhead. In my example of a qsort comparison, the function pointer call is also quite expensive. But in some other application like Windows event dispatch, it hardly matters.

Since you are using C++ you should study templates. A template function can accept a so-called function object which is just an object that implements operator() and it can accept function pointers. Passing a function object will allow the C++ compiler to inline and optimize almost all of the code involved.

2
  • Templates were the other way to manage this, and I still might use them, however I don't understand them very well (I'm still learning), so function pointers would be the easy way out. Commented Jun 7, 2011 at 6:46
  • GCC will know all the code that uses the pointer, however funct is probably going to be part of a class in another file (and a number of different methods in that class will use funct). Is GCC going to be able to optimize this away? Unfortunately, the code is sensitive enough performance wise to this that I have to think about it (g will probably be called more than a couple hundred thousand times) Commented Jun 7, 2011 at 6:56
2

Any modern compiler can (and will) easily optimize out (i.e. inline) calls made through function pointers is situations when the compiler knows where the pointer is pointing to at compile time.

In your specific example in general case the value of the pointer cannot be predicted at compile time at the point of the call, since it is passed from outside as a parameter of function funct. In situations when the function funct itself is small enough to get inlined, the run-time parameter gets eliminated and the whole code of funct gets "dissolved" in the functs caller context. In the value of the pointer is known in that caller context, then, again, the compiler can easily eliminate the call through the pointer.

Finally, if the function funct is relatively heavy (meaning it does not get inlined), the you should probably expect the compiler to generate an ordinary run-time call through the pointer from inside of funct. The potential for call elimination exists in this case as well, since the compiler can theoretically generate a separate version of funct for each compile-time value of g. For example, if you have

int funct(int x1, int x2, int x3, double (*f)(double));

which is called with only two possible arguments for parameter f

funct(rand(), rand(), rand(), g1);
...
funct(rand(), rand(), rand(), g2);

then the compiler can "reduce" it into two functions

int funct_g1(int x1, int x2, int x3);
int funct_g2(int x1, int x2, int x3);

without a function pointer parameters and with direct calls to either g1 and g2 inside. (Of course, this optimization is not in any way tied to function pointers and can be applied to any function parameter that is used with only a small fixed set of arguments. In fact, this is similar to C++ templates.) But I'm not aware of any compilers that would do anything like that.

1

The compiler will probably not optimize it, because the function funct can receive pointers to different functions, not just g, and they don't have to come from the same compiling unit (thus the compiler cannot assume it knows about all the possible calls).

You need to benchmark your code to see if the optimization you're talking about is necessary, and if it is - just do it. But unless funct calls g a lot, I wouldn't expect this to matter.

6
  • Compier can optimize function call via pointer, even if there are more than one calls, even if functions are in different translation units. It's called full program optimization, which is done at link time. Commented Jun 7, 2011 at 1:30
  • The distinction between compiler and linker isn't as clear cut as it was in the past. Nowadays optimization and code generation is done at link time, at run time, ... Commented Jun 7, 2011 at 2:33
  • 2
    Sometimes, gcc will simply produce two functions in such a situation: one for the case with the known function pointer and one for the general case. With this approach, the linker doesn't need to do anything special. Commented Jun 7, 2011 at 2:50
  • funct would probably call g a couple hundred thousand to a couple million times... maybe more. :) Commented Jun 7, 2011 at 6:50
  • @spot - then I would suggest not to rely on the compiler optimizations.
    – littleadv
    Commented Jun 7, 2011 at 7:07

Not the answer you're looking for? Browse other questions tagged or ask your own question.