Skip to content
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

Call to consteval function isn't folded to a constant #45257

Closed
ldionne opened this issue May 13, 2020 · 3 comments
Closed

Call to consteval function isn't folded to a constant #45257

ldionne opened this issue May 13, 2020 · 3 comments
Labels
bugzilla Issues migrated from bugzilla clang:codegen

Comments

@ldionne
Copy link
Member

ldionne commented May 13, 2020

Bugzilla Link 45912
Resolution FIXED
Resolved on Jun 25, 2020 07:57
Version trunk
OS All
CC @zygoloid,@Ralender

Extended Description

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: https://godbolt.org/z/MA9U8b

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 (http://eel.is/c++draft/expr.const#13):

> [...] 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).

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented May 13, 2020

This may not technically be a bug, but it is a serious deviation from the intent, and this is one of the primary reasons why Clang does not claim to support consteval yet.

@Ralender
Copy link
Collaborator

yeah, this isn't implemented yet.
i have a patch to fix this https://reviews.llvm.org/D76420

@Ralender
Copy link
Collaborator

the patch has landed and the problem should be fixed.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang:codegen
Projects
None yet
Development

No branches or pull requests

2 participants