https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99091

            Bug ID: 99091
           Summary: constexpr variable evaluated at runtime
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: barry.revzin at gmail dot com
  Target Milestone: ---

Consider the following (link to compiler explorer:
https://godbolt.org/z/jWsxsK)

#include <array>

static constexpr auto doy = []{
    std::array<int, 13> month_offset{};
    for (int m=1; m<=12;++m) {
        month_offset[m] = (153*(m > 2 ? m-3 : m+9) + 2)/5;
    }
    return month_offset;
}();

auto foo(int m) -> int {
    #ifdef LOCAL
    constexpr auto doy = []{
        std::array<int, 13> month_offset{};
        for (int m=1; m<=12;++m) {
            month_offset[m] = (153*(m > 2 ? m-3 : m+9) + 2)/5;
        }
        return month_offset;
    }();
    #endif

    return doy[m];
}

This is a fragment of code that does some calculation to figure out the date,
which isn't super important. If LOCAL is not defined (i.e. we declare the array
as a namespace-scope constexpr), the -O3 codegen of 'foo' is:

foo(int):
        movsx   rdi, edi
        mov     eax, DWORD PTR doy[0+rdi*4]
        ret

However, if we want to move the declaration of doy to be more local to the
calculation and compile with -DLOCAL, the codegen instead is (on -O3):

foo(int):
        pxor    xmm0, xmm0
        mov     rax, QWORD PTR .LC0[rip]
        movsx   rdi, edi
        mov     DWORD PTR [rsp-24], 275
        movaps  XMMWORD PTR [rsp-72], xmm0
        movdqa  xmm0, XMMWORD PTR .LC1[rip]
        mov     QWORD PTR [rsp-68], rax
        movaps  XMMWORD PTR [rsp-56], xmm0
        movdqa  xmm0, XMMWORD PTR .LC2[rip]
        movaps  XMMWORD PTR [rsp-40], xmm0
        mov     eax, DWORD PTR [rsp-72+rdi*4]
        ret

This can be alleviated by marked the local variable doy as being static
constexpr. Except that this prevents 'foo' from being a constexpr function
(can't have static variables). 

This just seems like bad codegen, I'm not sure there's any reason that the
compiler needs to do work here. It would be nice if the codegen with a local
constexpr variable were the same as if it were a non-local constexpr variable.

Reply via email to