Gcc 4.7 and constexpr recursive functions

I am losing constexpr recursion a constexpr and trying to see how it compiled, and I don’t understand under what circumstances gcc chooses recursion computation at compile time or at runtime.

I use the following factorial code:

 #include <iostream> constexpr unsigned int factorial(unsigned int i) { return i > 0 ? i*factorial(i-1) : 1; } int main(void) { std::cout << factorial(X) << std::endl; } 

and I change the value of x in the factorial.

  • When compiling without optimization, the expression is not evaluated at compile time.
  • When compiling with the -O1 flag -O1 expression is still not evaluated at compile time.
  • With -O2 expression is evaluated at compile time if x < 9 . After this value, the factorial is implemented as a built-in loop. Changing the value of the -fconstexpr-depth flag does not change anything.
  • With -O3 expression is evaluated at compile time if x < 7 . After this value, factorial is implemented embedded with the x86 xmm extension.
  • If I change the product by the sum in the factorial function, I get a compilation time calculation of up to 10000 or more, and decreasing or increasing the value of -fconstexpr-depth does not change anything.

Does anyone know what are the rules of gcc 4.7 for implementing a recursive function like compile time or runtime?

+4
source share
2 answers

constexpr guaranteed only at compilation, if necessary at compile time. For example, this ensures that it will be computed at compile time, because enum values ​​must be constant:

 enum { VALUE = factorial(X) }; cout << VALUE << endl; 

In any case, when it is not needed at compile time, it has the same effect as the inline declaration: it is just a hint, and the compiler can do whatever it wants.

Like inline , most compilers currently completely ignore your hint. For performance reasons, the compiler wants to be able to embed things even when you haven’t requested them, and has its own algorithm to determine when it’s not worth it, so why not take a look at the inline keyword?

+1
source

Declaring a constexpr function constexpr not mean that it will be evaluated at compile time. This means that it can be used to calculate the value that is required at compile time. In any other context, this is just an ordinary function, and it will be evaluated at runtime if the compiler does not determine that its evaluation at compile time satisfies the “as is” rule and is worth doing.

In other words, I expect you to find exactly the same compilation / runtime execution model if you leave constexpr outside the factorial declaration.

+1
source

All Articles