views:

424

answers:

8

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.

+6  A: 

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.

anon
I'm not quite at the stage where I'm ready to read the assembly output!
Joe
Re your most recent edit with `x` and `p`: yes, that's exactly the question I'm asking. I know it's difficult, that's why I was asking if it was possible or not!
Joe
As I said, it's possible. Does GCC do i? I don't know.
anon
IMHO the compiler may have it easier to optimize the code, if you change your function to `int myFunction(int thing)` and call it like `thing=myFunction(thing)`. In this way you omit all the indirections, and the result will be plain arithmetic that the compiler (probably) can easily optimize away.
frunsi
It's not just an int in the real code, it's a bit more complex.
Joe
Don't mind if it is a pointer to a struct, in this case the compiler has to apply pointer arithmetic anyway. Or at least use an address register (containing the address of the struct) and offsets for accessing the fields of the struct. This case may not make a difference after inlining.
frunsi
Thank you frunsi, that's a useful insight I hadn't considered.
Joe
A: 

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.

mikelong
+1  A: 

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.

ondra
C99 says that `extern inline` does cause stand-alone object code to be generated, and GCC will follow these odd rules if put into C99 mode. Otherwise, GCC's default behavior is what you've stated. (C89 doesn't say anything, and arguably those are better semantics.)
ephemient
+2  A: 

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.

frunsi
As C89 says nothing whatsoever about inlining, a C89 compiler is certainly free to inline any function it fancies. Of course, such a program might not link (which is the real issue here), but a compiler whith an integrated linker could get round this by performing a global code analysis.
anon
So I guess, a compiler might automatically inline non-static functions if all files are compiled and linked in a single step into an executable (not into an object file or library). Well, ok, but its usually not very practical ;) The "must be static" rule still applies otherwise.
frunsi
Depending on optimizer settings, size of function, frequency of calls, etc., GCC will inline non-static functions within the same compilation unit. It will still generate a non-inline function as well.
ephemient
@ephemient: Thx, good to know.
frunsi
Keep in mind that a compiler can pretty much do whatever it likes as long as the result matches the intent you wrote in the source code.As such a function can very well be inlined, or optimized away entierly without it being static or marked as inline. (e.g. gcc will easily do this in many scenarios).
nos
nos: why do you think gcc will optimize away a non-static function? It won't - at least not when it will produce an ELF file, without special compiler switches ;)
frunsi
You are right that it'll keep the (non static) function body around, however it can optimize away/inline calls to it within the same translation unit.
nos
+8  A: 
Nikolai N Fetissov
AWESOME discovery
Joseph Garvin
Although it spits out lots of spurious warnings about default destructors >_<
Joseph Garvin
A: 

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.

T.E.D.
Like I said in the question, I'm not worrying about optimization, I'm trying to learn more about the language and GCC. I certainly believe in measuring before optimizing but I think it's useful to at least know these things.
Joe
+5  A: 

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.

ntd
At least with GCC 4.4.2, it doesn't even need to be marked `inline`! (Although using `static` will avoid an extra copy of the function in the generated binary.)
ephemient
A: 

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.

tstenner