llvm / llvm/llvm-project

Miscompilation on x86_64

Open
#205,291 2 comments 0 reactions 0 assignees View on GitHub
backend:X86 miscompilation
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.