Open TedLyngmo opened 3 months ago
@llvm/issue-subscribers-c
Author: Ted Lyngmo (TedLyngmo)
@llvm/issue-subscribers-clang-frontend
Author: Ted Lyngmo (TedLyngmo)
Agreed that this is not a valid optimization in C; Clang is marking the local variable as being available for NRVO: https://godbolt.org/z/PhdKhqPPc
|-FunctionDecl <line:8:1, line:12:1> line:8:3 used test 'S (S *)'
| |-ParmVarDecl <col:8, col:11> col:11 used q 'S *'
| `-CompoundStmt <col:14, line:12:1>
| |-DeclStmt <line:9:5, col:23>
| | `-VarDecl <col:5, col:22> col:7 used s 'S' nrvo cinit
Note GCC has the opposite issue dealing with C++ where it optimizes away the comparison too early even with language mandatory NVRO, see https://cplusplus.github.io/CWG/issues/2868.html and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414 . Note the optimizing away the comparison is how GCC handles this case here even though it does NVRO; though the NVRO is done iff the struct return has no address taken on it (after many optmizations).
Here is a replacement function where GCC does not do NVRO and the comparison is still kept around (but still does return slot optimization
[RSO]) while clang does the NVRO [incorrectly]:
S test(S* q) __attribute__((noinline));
S test(S* q) {
S s = {0, 0, 0, 0};
void *a = q;
void *a1 = &s;
__asm__("":"+r"(a));
__asm__("":"+r"(a1));
result = a1 == a;
return s;
}
This C program exits with
1
even though it should exit with0
. To the best of my knowledge, NRVO is not allowed in C: