Calling functions with constant optimization in C / C ++

If you have a function call with constants, it has no side effects and is independent of anything, for example:

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

Is the feature on? Or maybe the function is evaluated at compile time, and the result of this evaluation is inserted instead of calling the function?

+4
source share
7 answers

I tried to compile this using a pretty old gcc -

#include <iostream> int foo(int a,int b) { return a+b; } int main() { std::cout << foo(100, 123) ; } 

And the main compiled for this is

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

So he compiled the add at compile time, getting 223.

Obviously, the results depend on your code and compiler, but this shows that it can and does both built-in and computes the addition at compile time, if possible.

+7
source

Not in C ++. They will not be executed at compile time in the same way as the compiler does. However, this cannot be forced.

However, with C ++ 11, you can use constexpr to make sure it is evaluated at compile time, for example:

 constexpr int get_five() {return 5;} 

So you can rewrite your function as:

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

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

From Wikipedia:

If a constexpr function or constructor is called with arguments that are not constant expressions, the call behaves as if the function was not constexpr, and the resulting value is not a constant expression. Similarly, if the expression in the returned expression constexpr function does not evaluate the constant expression for a particular call, 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 

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

+4
source

If you define this in the header file, then there is a high probability that it will be embedded. If the integral constants of compilation time are used as arguments, the compiler should be able to perform this function at compile time.

Despite the lack of such a guarantee, you must trust your compiler. They optimize your code very well. If you want the function to be executed at compile time, you can add constexpr overload (C ++ 11 only):

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

I 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 compiles as follows:

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

Therefore, you can see that it actually executes at compile time.

+2
source

Whether such optimizations are performed not as a certain part of the C and C ++ languages. In fact, the compiler is free to optimize as it sees fit, as long as the resulting code is valid in accordance with the source code. In general, at higher levels of optimization, this call can be either built-in, or if call sites are always passed in constants (values ​​known at compile time), the result can be calculated at compile time, and all service data at runtime is completely excluded.

Common cases in which the optimizing compiler will choose non-built-in functions:

  • Recursive functions
  • When he prefers size over speed, or if the attachment will greatly distort the size of the binary end file

Another problem that should be noted is that inlining will change the relationship of the function.

Compiling the following code in GCC and g ++ using -O3 :

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

Results in the following assembler:

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

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

0
source

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

If you want the function to be inline, you can always declare it using the inline keyword:

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

but these well-targeted tips should generally be avoided, as most compilers decide better what functions are built-in than most programmers do.

0
source

A possible scenario of how this function can be calculated at compile time:
1) the built-in foo function of the compiler during one of the inline optimization phases.
2) during constant propagation, the phase optimization phase can “propagate” the value of variables that are known at compile time, that is, constants and constant expression.

NB: you don’t know exactly if the function is turned on until you see the assembler code of your program. Even if you use the inline specifier. The compiler can ignore this specifier or built-in function without this specifier.

0
source

Source: https://habr.com/ru/post/1432929/


All Articles