1

I am reading Bjarne's A Tour of C++ and he has this example in section 1.6 Constants.

constexpr int dmv = 17; // dmv is a named constant
int var = 17; // var is not a constant
const double sqv = sqrt(var); // sqv is a named constant, possibly computed at run time

My question is related to his comment on the last line

... possibly computed at run time

From looking at the code, the value var, a numeric literal of 17 isn't going to be changed anywhere in the code. Why is it not evaluated at compile time by the compiler?

I saw this question's answer when looking and it makes sense that const is used for semantics and more for the programmer than the compiler. But my main question is:

Can the compiler not optimize this and if not is it because it is too much to ask of the compiler to optimize?

EDIT: The part of the compiler I would like to optimize is to compute sqv since var is not changed anywhere in the program.

heretoinfinity
  • 1,528
  • 3
  • 14
  • 33
  • 2
    Note the word "possibly" in your quote. The C++ language simply doesn't specify whether this value will be computed at runtime or compile time. If you wrote your own C++ compiler, you could decide when this value is computed. – Drew Dormann Aug 13 '23 at 14:58
  • What part of `int var = 17;` do you want the compiler to optimize? – Eljay Aug 13 '23 at 14:58
  • 2
    The std::sqrt will be constexpr in C++26 ... until then there are no way how you get compile time expression from sqrt. That does not mean compiler may not optimize it, but standard can't require it in any manner. – Öö Tiib Aug 13 '23 at 15:05
  • @Eljay, I added a comment – heretoinfinity Aug 13 '23 at 15:06
  • Whereas `sqv` is **not** a constant expression, compiler might, with as-if rule, optimize code to not call `sqrt` at runtime. – Jarod42 Aug 13 '23 at 16:18

3 Answers3

5

Can the compiler not optimize this

It may be able to do it, but it's not required to be able to do it (until C++26 where std::sqrt has been made constexpr).

Even in C++11 mode, both g++ 13.2 and clang++ 16 optimize this program

#include <cmath>
int main() {
    constexpr int dmv = 17;            // dmv is a named constant
    int var = 17;                      // var is not a constant
    const double sqv = std::sqrt(var);
    return static_cast<int>(sqv);
}

into this assembly

main:
        mov     eax, 4
        ret
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Is the compiler really required to evaluate `std::sqrt` at compile time if it's `constexpr`? I'm pretty sure that it's merely allowed to do constant folding, but unless it's used in a context where constant expressions are required, it isn't forced to use `constexpr` evaluation. – Jan Schultke Aug 13 '23 at 15:45
  • @JanSchultke No, but a `constexpr` function is required to _be able_ to do it. It doesn't have to do it in all situations though, but if it's not able to do it, then it can't be used in situations where a constant expression is required, like in template parameters or `constinit` variables etc. – Ted Lyngmo Aug 13 '23 at 15:54
  • Could you clarify what the assembly means? Return a value of 4? – heretoinfinity Aug 19 '23 at 20:31
  • 1
    @heretoinfinity Exactly. It's calculated the result at compiletime even though its not required by the standatd. – Ted Lyngmo Aug 19 '23 at 20:39
2

Can the compiler not optimize this

It can in some situations, like this one. In fact, std::sqrt will be constexpr in C++26, so you will be able to do something like this:

constexpr int var = 17;
constexpr double sqv = sqrt(var);

Demo

Note: GCC 13.2 apparently accepts this code even with -std=c++11. Clang 16.0 does not.

In your example, since var is not constexpr or even const, and sqrt is not yet constexpr, the call is not required to be made at compile time. However, if the compiler figures out that the value of var at the time of the call to sqrt is always 17, then it could also optimize the call because sqrt is a pure function. It would not go against the standard.

Nelfeal
  • 12,593
  • 1
  • 20
  • 39
1

a numeric literal of 17 isn't going to be changed anywhere in the code. Why is it not evaluated at compile time by the compiler?

What may or may not be evaluated at compile time is not 17, but the result of sqrt() of 17. A compiler may be smart enough to know what this mysterious function from the standard library named "sqrt" does, and evaluate the result of sqrt(17), and then insert the actual, raw, numerical value you get from applying the sqrt operation to 17, into the code. Or, the compiler may not know that, and generate the code that calls sqrt, here.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148