llvm / llvm/llvm-project

[ArgumentPromotion] Miscompile with union type-punning at -O3

Open
#209,450 2 comments 0 reactions 0 assignees View on GitHub
llvm:optimizations
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

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.