Miscompilation on x86_64
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The assertion in the following code should pass, but fails with `-O1` and above ([Godbolt link](https://godbolt.org/z/sxWxarvsf)). As far as I can tell there should not be any undefined behavior in the code. This seems to happen since Clang 18, and still happens with "clang (trunk)" on Godbolt. The issue seems to be purely in `test_main`, the other two functions are only necessary to demonstrate the problem. It looks like the value of `a` is stored in the lower 8 bits of a register (`r13` in the Godbolt example) whose upper 56 bits still contain some other value. Clang then uses the whole 64-bit register in a `lea`, leading to an incorrect value of `b.second`.
```cpp
// Compile with "clang++ -O1 -std=c++20 main.cpp"
#include
#include
struct StructA {
signed char value;
};
struct StructB {
StructA first;
int second;
};
__attribute__((noinline)) int test_inner(int const&, StructB b) { return b.second; }
__attribute__((noinline)) std::vector test_main(std::vector const& as)
{
std::vector track_keys;
for (StructA a : as) {
track_keys.emplace_back(test_inner(13, StructB{a, 2}));
}
return track_keys;
}
int main()
{
assert(test_main({StructA{0}}).front() == 2);
}
```
Contributor guide
Research direction
Reproduce the failure with main.cpp using clang++ -O1 -std=c++20 and compare the generated x86_64 code with the Godbolt example. Start at the x86_64 lowering for test_main and trace how StructB{a, 2} is passed to test_inner. Done means the assertion passes at -O1 and above without changing the sample's intended behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100