开发者

Will GCC inline a function that takes a pointer?

开发者 https://www.devze.com 2022-12-16 04:30 出处:网络
I have a function which operates on开发者_开发百科 piece of data (let\'s say, an int), and I want to change it in place by passing a reference to the valule. As such, I have the function: void myFunct

I have a function which operates on开发者_开发百科 piece of data (let's say, an int), and I want to change it in place by passing a reference to the valule. As such, I have the function: void myFunction(int *thing) { ... }. When I use it I call it thus: myFunction(&anInt).

As my function is called frequently (but from many different places) I am concerned about its performance. The reason I have refactored it into a function is testability and code reuse.

Will the compiler be able to optimize the function, inlining it to operate directly on my anInt variable?

I hope you'll take this question in the spirit in which it's asked (i.e. I'm not prematurely worrying about optimisation, I'm curious about the answer). Similarly, I don't want to make it into a macro.


One way to find out if the function is inlined is to use -Winline gcc option:

-Winline
  Warn if a function can not be inlined and it was declared as inline.
  Even with this option, the compiler will not warn about failures to inline
  functions declared in system headers.

  The compiler uses a variety of heuristics to determine whether or not to
  inline a function. For example, the compiler takes into account the size
  of the function being inlined and the amount of inlining that has already
  been done in the current function.  Therefore, seemingly insignificant
  changes in the source program can cause the warnings produced by -Winline
  to appear or disappear.


GCC is quite smart. Consider this code fragment:

#include <stdio.h>

void __inline__ inc(int *val)
{
    ++ *val;
}

int main()
{
    int val;

    scanf("%d", &val);

    inc(&val);

    printf("%d\n", val);

    return 0;
}

After a gcc -S -O3 test.c you'll get the following relevant asm:

...
call    __isoc99_scanf
movl    12(%rsp), %esi
movl    $.LC1, %edi
xorl    %eax, %eax
addl    $1, %esi
movl    %esi, 12(%rsp)
call    printf
...

As you can see, there's no need to be an asm expert to see the inc() call has been converted to an increment instruction.


There are two issues here - can the code be optimised, and will it. It certainly can be, but the "will" depends on the mood the optimiser is in. If this is really important to you, compile the code and take a look at the assembly language output.

Also, you seem to be conflating two issues. An inlined function effectively has its body pasted at the call site. Whether or not you are using pointers is neither here nor there. But you seem to be asking if the compiler can transform:

int x = 42;
int * p = & x;
* p = * p + 1;

into

x = x + 1;

This is much more difficult for the optimiser to see.


It should not matter whether the argument is a pointer or not.

But first, if the compiler should automatically inline the function, it must be static. And it must be contained in the same compilation unit. NOTE: we are talking about C, not C++. C++ inline rules differ.

If it is not possible to have the function in the same compilation unit, then try global optimizations (check documentation of your compiler for details).

C99 gives you an "inline" keyword, just as in C++. Which lifts the restriction to the compilation unit.

Here is some further information.


It will (or at least can). There are some reasons where the function cannot be inlined - e.g. when you try to access a pointer of the function (calling function by reference - you are accessing parameters by reference which is ok). There may be other situation (static variables? unsure)

Try to declare the function with "extern inline" - this prevents the compiler from emitting the standalone body. If it cannot inline the function, it will emit an error.


If you're concerned about the compiler generating suboptimal code and want to change a simple valuetype, declare your function as int myFunction(int) and return the new value.


What compiler version are you using? With what options? On what platform?

All these questions effect the answer. You really need to compile the code and look at the assembly to be sure.


This looks to me like a classic case of premature optimization. Do you really know there is a performance issue here? One worth wasting your valuable time worrying about. I mean, really know? Like, have you measured it?

By itself this isn't too bad, but if you take this attitude over a large amount of code, you can do some serious damage and waste a large amount of deveolpement and maintanence time for no good reason.

0

精彩评论

暂无评论...
验证码 换一张
取 消