I am wondering if GCC will leave arithmetic with fixed values to be executed at run-time or if it will set it to it's answer, eg.
const float halfPi = M_PI/2;
Will it "boil down" the equation and set
const float halfPi = 1.57079;
Or leave the arithmetic for run-time?
Well... if we were talking about integrals the answer would be a clear-cut yes (under the general term Constant Folding). Even long-winded computations can be done at compile-time... and this is actually required for templates non-type parameters evaluation and (now) constexpr
variables.
In the case of floating point representations, things get a bit complicated as soon as computations get a bit more complicated. The issue is that floating point representations of different sizes (and thus precisions) will yield different results for the same base inputs.
To understand why, suppose that float
has, at most, 5 digits of precisions:
5.0000 + 0.00001
-> 5.00001
-> 5.0000 (truncation to 5 digits)
5.0000 + 0.00001 + ... + 0.00001 (10 times)
-> 5.0000 + 0.00001 + ... + 0.00001 (9 times)
-> 5.0000 + 0.00001 + ... + 0.00001 (8 times)
-> ...
-> 5.0000
Surprising... right ? If the compilation is done at runtime, then the result may vary depending on whether a register (with larger bitwidth) is used or not.
Therefore, whether constant folding occurs probably depends on the set of optimization flags you use. For example, for gcc, this might be controlled by -freciprocal-math
(no idea really). Because even though the compiler certainly can do it, you might be telling it not to (unknowingly).
So the only sure way to test this is to check the compiler output; either by inspecting the object code OR by asking the compiler to emit assembly. And you will need to check this output for every combination of options that you use.
Today is your lucky day, because you find out about Agner Fog and his amazing in depth c++
manuals! If you look at section 8.2
of this one you will see that basically all compilers are capable of constant folding.
Although to make sure it does occur in this particular case with your compiler options, you should check the assembly output as suggested above (use -S
). I like to put something like asm("MY_LABEL:");
nearby in the code to make it easy to find, but bear in mind that this can change the meaning of the code, and hence how the compiler interprets it. In this case I don't believe it would change anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With