-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[C++20] [constexpr] Should we cache the result of constexpr/consteval expression? #61425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@llvm/issue-subscribers-c-20 |
I tried doing exactly that by simply having a |
@llvm/issue-subscribers-clang-frontend |
Also relevant discussion: #13222 |
I feel that discussion didn't talk a lot. Let's try to mark it as duplicate and track in this one. (Since that one is from llvmbot. So it looks a little bit outdated to me.) |
What happens if a template specialization is added between calls? Or with all the 'unique unevaluated lambda types' tricks? (https://github.com/DaemonSnake/unconstexpr-cpp20 for example)
I guess it might be possible to calculate when caching is possible, but I don't think it can trivially work. There's also an easy workaround here with constexpr variables. |
Sent https://reviews.llvm.org/D146410 to get a more precise feeling for the proposed solution. There are several problems for the patch. But it can solve the problem in the issue and it can pass all the test except After applying the above patch, the output for the reproducer would be:
It looks pretty good to me.
The explicit specialization of functions after instantiation is not allowed. I guess you may want to ask for the following case?
It shows that we will take Although the possibility should be pretty low, the biggest problem of the solution is that the current hash algorithm is not solid in theory. It implies that it is possible the compiler may treat two different constexpr function calls as the same. In another way, the Then about the So personally, I prefer to the current hash values (unsigned). The second problem may be the style. To be honest, the patch above is a little bit ugly. And there are much more places I didn't touch. I want to move the process of evaluating expressions to ASTContext rather than Expr. But this requires a lot of change which I don't like. But I guess we have to do so if we want to make this. Other problems I can see is the concern for correctness. This may be the most important thing. But it is hard to discuss without the details. For
The second call to |
We'd need to be very careful. I'm not sure that users can themselves get into a situation where constant evaluation would lead to a different result the second time if the first evaluation was successful. so we might be able to have a list of builtins that exclude an evaluation from caching. maybe that would be enough? |
I think this probably needs an RFC. But as Corentin says, I'm VERY concerned here. I think a less dangerous solution is the one that @tbaederr is working on, which is the new bitcode based interpreter, which can then be better cached/executed more quickly. |
FYI the results with the new constant expression interpreter are:
|
@tbaederr do we know what kind of witchcraft GCC is performing? it's very impressive performance numbers |
You were too fast, I just updated them. My clang numbers were with msan enabled, sorry. |
@tbaederr the numbers looks pretty good! Is there is RFC or a design doc that I can learn the higher level design? And if the |
In terms of high-level documentation, there is https://clang.llvm.org/docs/ConstantInterpreter.html, but large parts of that are out of date. I haven't found the time to update it yet. |
I believe this would be quite useful if compiler could promise to do so. constexpr std::string func() { ... }
constexpr size_t N = func().size();
template <size_t M>
constexpr std::array<char, M> make_data() {
std::string str = func();
std::array<char, M> result(str.begin(), str.end());
result[M - 1] = 0;
return result;
}
constexpr auto data = make_data<N + 1>(); As shown above, I have to calculate func twice, so that I can store std::string into std::array which can cross the boundary between compiling and runtime. |
I found this one when I investigate the building time in modules.
The reproducer:
Let's run it with:
The result in my machine shows:
So now Clang doesn't cache the result of
constexpr
/consteval
clearly. This is significant when we try to use some metaprogramming techniques. Is there any special reason?The text was updated successfully, but these errors were encountered: