[ArgumentPromotion] Miscompile with union type-punning at -O3
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
The following test case is miscompiled at `-O3`:
```c
struct s1 { double d; };
struct s2 { double d; };
union u { struct s1 x; struct s2 y; };
static double f(struct s1 *a, struct s2 *b) {
a->d = 1.0;
return b->d + 1.0;
}
int main() {
union u a;
a.x.d = 0.0;
if (f(&a.x, &a.y) != 2.0)
abort();
return 0;
}
```
```
$ clang -O3 -flto test.c -o test && ./test
Aborted
```
Expected result should returns 0 as both pointers refer to the same union memory via union.
`ArgumentPromotion` promotes b because it is only read and moves the load before the call. So the load happens too early and reads the old value 0.0 instead of the updated value 1.0.
TBAA says the store and load cannot refer to the same memory because they use different types. But since they are inside a union, they actually can refer to the same memory.
The problem goes away with `-fno-strict-aliasing` and above test case passes.
Contributor guide
Research direction
Start by compiling the reported test case with clang -O3 -flto and confirm that it aborts, then compare with -fno-strict-aliasing. Read the ArgumentPromotion pass and the TBAA behavior involved in the union access; done means the regression test returns normally at -O3 while preserving the expected optimization behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100