testcase: constexpr void mul2(int &a, const int b) { a = b * 2; } int test = []() {int a; mul2(a, 123); return a;}(); int test2 = []() {int a = 0; mul2(a, 123); return a;}(); output for GCC trunk with -O3 -std=c++17 _GLOBAL__sub_I_test: movl $246, test(%rip) ret test2: .long 246 test: .zero 4 simple testcase: int test3 = []() {int a; a = 5; return a;}(); _GLOBAL__sub_I_test: movl $5, test(%rip) ret test: .zero 4
I think the uninitialized variable makes the initialization not constexpr (and indeed gcc/clang complain if you try to declare test constexpr). Then we hit the well-known missed optimization that gcc is unable to convert a dynamic initialization into a static initialization even in the most trivial constant cases.
(In reply to Marc Glisse from comment #1) > I think the uninitialized variable makes the initialization not constexpr > (and indeed gcc/clang complain if you try to declare test constexpr). Then > we hit the well-known missed optimization that gcc is unable to convert a > dynamic initialization into a static initialization even in the most trivial > constant cases. Then need to mark this bug as duplicate, but where that bug in GCC bugzilla, which about that well-known missed optimization?
Another testcase: int test4 = []() constexpr {int a = a; a = 5; return a;}(); GCC is able compile this, so it "think" this is valid constexpr lambda, but anyway doing this: _GLOBAL__sub_I_test4: movl $5, test4(%rip) ret test4: .zero 4
For the original testcase except for test4, it is optimized for C++20 and not C++17. Most likely because lambdas are considered constexpr if they can be such. In test4 I suspect the uninit variable is making it not considered constexpr.