[llvm-bugs] [Bug 45912] New: Call to consteval function isn't folded to a constant

via llvm-bugs llvm-bugs at lists.llvm.org
Wed May 13 12:57:41 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=45912

            Bug ID: 45912
           Summary: Call to consteval function isn't folded to a constant
           Product: clang
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: LLVM Codegen
          Assignee: unassignedclangbugs at nondot.org
          Reporter: ldionne at apple.com
                CC: llvm-bugs at lists.llvm.org, neeilans at live.com,
                    richard-llvm at metafoo.co.uk

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

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200513/29d79f52/attachment.html>


More information about the llvm-bugs mailing list