clang inline func arg eval is too eager
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
On a call to an inline function, it is better to postpone the argument eval to the real using branch, g++ does it this way, but clang does not:
```c++
#include
#include
__attribute__((pure)) int fake_pure();
inline __attribute__((always_inline)) int foo(int cond, int x) {
if (cond)
return x*2;
else
return 0;
}
int main(int argc, char* argv[]) {
int cond = argc >= 2 && atoi(argv[1]);
return foo(cond, fake_pure());
}
// defined in another file such as fake_pure.cpp
// __attribute__((noinline)) int fake_pure() {
// printf("fake pure\n");
// return 1;
// }
```
In the above code, `fake_pure` is used to trigger argument eval eager(clang) or lazy(g++).
see: https://godbolt.org/z/j7cWEnKdj
This is useful in some other case such as postpone time consuming pointer chasing to the real usage branch:
```c++
#include
#include
struct A {
int x;
A* next;
};
__attribute__((pure)) A* get_a(); // defined in another source file
inline __attribute__((always_inline)) int foo(int cond, int x) {
if (cond)
return x*2;
else
return 0;
}
int main(int argc, char* argv[]) {
int cond = argc >= 2 && atoi(argv[1]);
return foo(cond, get_a()->next->next->next->next->x);
}
```
see: https://godbolt.org/z/668MfsM9n
Contributor guide
Research direction
Reproduce the eager-versus-lazy behavior using the two C++ examples and the linked Compiler Explorer cases, comparing clang with g++. Start by tracing how clang handles argument evaluation when an always_inline function is inlined. Done means unused arguments are not evaluated on branches where the inlined function does not use them, while the shown behavior remains correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100