coredump
coredump

Reputation: 3117

Function calls with constants optimization in C/C++

If you have function call with constants, it has no side effects and it is not dependent on anything, like the following:

int foo(int a,int b)
{         
  return a+b;   
}

Does the function get inlined? Or, perhaps is the function evaluated at compile-time, with the result of this evaluation inserted in place of the function call?

Upvotes: 4

Views: 904

Answers (7)

ThomasMore
ThomasMore

Reputation: 188

Possible scenario how this function can be calculated in compile time:
1) compiler inline foo function during one of inlining optimization phase.
2) during constant propagation optimization phase compiler can "propagate" value of variables that are known in compile-time, i.e. constants and constant expression.

NB: You'll never know exactly whether the function is inlined until you see the assembler code of your program. Even if you use inline specifier. Compiler may ignore this specifier or inline function without this specifier.

Upvotes: 0

mfontanini
mfontanini

Reputation: 21910

If you define that in the header file, then there's a great chance of it being inlined. If you're using integral compile-time constants as its arguments, then the compiler should be able to execute that function on compile-time.

Even though there is no such guarantee, you should trust your compiler. Their pretty good at optimizing your code. If you want to ensure that the function is executed on compile time, you can add a constexpr overload(C++11 only):

constexpr int foo(int a,int b){
    return a+b;
}

I've tried the following snippet:

int add(int a, int b) {
    return a + b;
}

int main() {
    return add(5, 2);
}

When compiled using GCC and the -O3 flag, it gets compiled to this:

0x08048300 <+0>:    mov    $0x7,%eax
0x08048305 <+5>:    ret

Therefore, you can see that it is actually being executed on compile time.

Upvotes: 2

Mike Kwan
Mike Kwan

Reputation: 24477

Whether such optimisations are performed are not a defined part of the C and C++ languages. Essentially, the compiler is free to optimise as it sees fit as long as the resulting code is valid according to the source. In the general case, at higher optimisation levels, this call could be either inlined or if the call sites always pass in constants (values known at compile time), the result can be calculated at compile time and any runtime overhead completely avoided.

The general cases under which case an optimising compiler will choose not to inline functions are:

  • Recursive functions
  • When it is favouring size over speed or if inlining would greatly skew the size of the end binary

One more issue to note is that inlining will change the linkage of a function.

Compiling the following C code on both GCC and G++ with -O3:

int foo(int a, int b) {
    return a+b;
}

int main(void)
{
    return foo(1, 2);
}

Results in the following assembly code:

00000000004004e0 <main>:
main():
  4004e0:       b8 03 00 00 00          mov    $0x3,%eax
  4004e5:       c3                      retq

Upvotes: 1

jcoder
jcoder

Reputation: 30055

I tried compiling this using a fairly old gcc -

#include <iostream>

int foo(int a,int b)
{
    return a+b;
} 


int main()
{
    std::cout << foo(100, 123) ;
}

And main compiled to this -

LFB1439:
    subq    $8, %rsp
.LCFI1:
    movl    $223, %esi
    movl    $_ZSt4cout, %edi
    call    _ZNSolsEi
    xorl    %eax, %eax
    addq    $8, %rsp
    ret

So it compiled the addition at compile time getting 223.

Obviously the results depend on your code and compiler but this shows that it can and does both inline and compute the addition at compile time if it can.

Upvotes: 6

Philipp
Philipp

Reputation: 69773

It depends on the compiler and on the optimization settings, but in general you can assume that any sufficiently advanced compiler will inline such a trivial function when you switch on at least a bit of optimization.

When you want to make sure that the function is inlined, you can always declare it with the inline keyword:

inline int foo(int a,int b){
    return a+b;
} 

but such well-intended hints should generally be avoided, because most compilers are better at deciding which functions to inline than most programmers.

Upvotes: 0

Minion91
Minion91

Reputation: 1929

you can check the assembly listing to see if it gets inlined, but as mentioned earlier, it is compiler specific.

Upvotes: 0

ronalchn
ronalchn

Reputation: 12335

Not in C++. They will not be executed at compile time just like that - unless the compiler magically does it. However, this cannot be forced.

However, with C++11, you can use constexpr to ensure it is evaluated at compile time, eg:

constexpr int get_five() {return 5;}

Thus, you can rewrite your function as:

constexpr int foo(int a,int b)
{         
  return a+b;   
}

Note that you do not have to worry if the arguments to this function are not always constant.

From Wikipedia:

If a constexpr function or constructor is called with arguments which aren't constant expressions, the call behaves as if the function were not constexpr, and the resulting value is not a constant expression. Likewise, if the expression in the return statement of a constexpr function does not evaluate to a constant expression for a particular invocation, the result is not a constant expression.

This means that foo(1,1) will be constant, but:

int i,j;
cin >> i >> j;
foo(i,j) // this is not constant

Reference: http://en.wikipedia.org/wiki/C%2B%2B11#constexpr_-_Generalized_constant_expressions

Upvotes: 4

Related Questions