Issue |
140009
|
Summary |
Clang emits llvm.memcpy for closure type without lambda-capature in C++20 but not in C++17
|
Labels |
clang:codegen
|
Assignees |
|
Reporter |
MaskRay
|
In C++20, a closure type without lambda-capture has a defaulted default constructor, different from previous versions of standards.
https://eel.is/c++draft/expr.prim.lambda#capture
> The closure type associated with a lambda-_expression_ has no default constructor if the lambda-_expression_ has a lambda-capture and a defaulted default constructor otherwise.
This leads to a redundant `memcpy` call for the following C++ code: https://godbolt.org/z/9xbM5fj5W
```cpp
#define F(a, b) { \
auto check = [](const char *, long) {}; \
check(a, b); \
asm("// %0 %1" : : "r"(a), "r"(b)); }
void foo() { F("hello", 3); }
```
```llvm
// -std=c++17 -O0
%class.anon = type { i8 }
@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1
define dso_local void @foo()() #0 {
%1 = alloca %class.anon, align 1
call void @"foo()::$_0::operator()(char const*, long) const"(ptr noundef nonnull align 1 dereferenceable(1) %1, ptr noundef @.str, i64 noundef 3)
call void asm sideeffect "// $0 $1", "r,r,~{dirflag},~{fpsr},~{flags}"(ptr @.str, i32 3) #2
ret void
}
// -std=c++20 -O0
%class.anon = type { i8 }
@__const.foo().check = private unnamed_addr constant %class.anon undef, align 1
@.str = private unnamed_addr constant [6 x i8] c"hello\00", align 1
define dso_local void @foo()() #0 {
%1 = alloca %class.anon, align 1
call void @llvm.memcpy.p0.p0.i64(ptr align 1 %1, ptr align 1 @__const.foo().check, i64 1, i1 false)
call void @"foo()::$_0::operator()(char const*, long) const"(ptr noundef nonnull align 1 dereferenceable(1) %1, ptr noundef @.str, i64 noundef 3)
call void asm sideeffect "// $0 $1", "r,r,~{dirflag},~{fpsr},~{flags}"(ptr @.str, i32 3) #3
ret void
}
```
In -O0, the `memcpy` is retained, and leads to something like `movb .L__const.foo().check(%rip), %al` on x86-64.
A redundant capture `auto check = [x=a](const char *, long) {};` suppresses the `llvm.memcpy` intrinsic (but introduces a useless `const char*` store).
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs