<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Call to consteval function isn't folded to a constant"
href="https://bugs.llvm.org/show_bug.cgi?id=45912">45912</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Call to consteval function isn't folded to a constant
</td>
</tr>
<tr>
<th>Product</th>
<td>clang
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>LLVM Codegen
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedclangbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>ldionne@apple.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
</td>
</tr></table>
<p>
<div>
<pre>The following program calling a consteval function causes code to be emitted to
compute the result of maxFoo() at runtime, when one would expect it to be
computed at compile-time:
$ cat <<EOF | clang++ -xc++ - -std=c++2a -Os -S -o a.s && cat a.s
#include <array>
#include <algorithm>
struct Foo { int i; };
static constexpr std::array<Foo, 3> foos = {{{1}, {2}, {3}}};
static int consteval maxFoo() {
auto it = std::max_element(foos.begin(), foos.end(), [](auto lhs, auto
rhs) {
return lhs.i < rhs.i;
});
return it->i;
}
int main() { return maxFoo(); }
EOF
Here's a few interesting observations:
1. This only happens when -Os or -O1 are used.
2. Even slight modifications of the above code will cause it to be inlined, for
example implementing `maxFoo()` equivalently but in a single expression.
3. The same issue happens whether `consteval` is used or not (which leads me to
think this is a codegen issue, not a front-end issue).
Godbolt link: <a href="https://godbolt.org/z/MA9U8b">https://godbolt.org/z/MA9U8b</a>
After playing around and debugging Clang for a bit, I am fairly confident that
this is not a bug per-se, but only an important QOI issue. In particular, I
think Clang behaves correctly with respect to the Standard, which only says
about immediate functions (<a href="http://eel.is/c++draft/expr.const#13">http://eel.is/c++draft/expr.const#13</a>):
> [...] An expression or conversion is an immediate invocation if
> it is a potentially-evaluated explicit or implicit invocation of
> an immediate function and is not in an immediate function context.
> An immediate invocation shall be a constant expression.
This doesn't talk about codegen, since the Standard doesn't have such a notion.
Also, Clang does treat `maxFoo()` as a constant expression, and in fact the
front-end even calculates the result properly in an APValue -- so Clang is
*correct* as far as the Standard is concerned.
However, the code generation appears to never be passed that knowledge, and as
a result it can sometimes fail to fold the immediate call, depending on
optimization levels. Since the intent of consteval was *specifically* to make
sure that no code is generated for such calls, I would argue this is an
important QOI issue (if we're being pedantic), and straight up a bug (as far as
99% of users are concerned).</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>