llvm / llvm/llvm-project

[clang] no stack reuse for temporaries created without a `MaterializeTemporaryExpr`

Open
#180,645 2 comments 0 reactions 0 assignees View on GitHub
clang:codegen missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

A [couple of testcases](https://godbolt.org/z/KrPejbhh1):

```c++
#include

void g(std::string = {});

void f() {
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
g();
}

struct X {
X();
~X();
int data[32];
};

void h() {
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
X();
}
```

In both cases, the stack usage grows linearly with the number of times the body is repeated.

The problem appears to be that the logic in CodeGen for generating LLVM lifetime markers is part of the handling for `MaterializeTemporaryExpr`, but we don't create `MaterializeTemporaryExpr` nodes for the above constructs. Instead we get:

```
| | `-CXXBindTemporaryExpr 'std::string':'std::basic_string' (CXXTemporary 0x43009f70)
| | `-CXXConstructExpr 'std::string':'std::basic_string' 'void () noexcept(is_nothrow_default_constructible>::value)' list
```

in the first case and

```
| `-CXXBindTemporaryExpr 'X' (CXXTemporary 0x4300dc40)
| `-CXXTemporaryObjectExpr 'X' 'void ()'
```

in the second case.

For the first case, we should probably create lifetime markers around the allocas we create for function parameters.

For the second case, we should probably create `MaterializeTemporaryExpr`s because [the language rules say a temporary materialization occurs here](https://eel.is/c++draft/expr.context#2.sentence-6).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.