https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127922
Bug ID: 127922
Summary: Wrong code with -flto: unsigned _BitInt(N) store does
not alias _BitInt(N) load
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: lto
Assignee: unassigned at gcc dot gnu.org
Reporter: kyuwoncho18 at gmail dot com
Target Milestone: ---
Component: lto
godbolt: https://godbolt.org/z/K3jKsvc4b
GCC trunk miscompiles this at `-O2 -flto`:
```c
#include <stdio.h>
typedef _BitInt(17) S;
typedef unsigned _BitInt(17) U;
__attribute__((noinline)) S f(S *p, U *q)
{
*p = 1;
*q = 2;
return *p;
}
int main(void)
{
S x = 0;
S result = f(&x, (U *)&x);
printf("%d\n", (int)result);
return result == 2 ? 0 : 1;
}
```
```console
$ gcc -std=c23 -O2 t.c && ./a.out
2
$ gcc -std=c23 -O2 -flto t.c && ./a.out
1
$ gcc -std=c23 -O2 -flto -fno-strict-aliasing t.c && ./a.out
2
```
Expected `2`: C23 6.5.1p7 (C17 6.5p7) allows an object to be accessed through
the signed or unsigned type corresponding to its effective type, and C23
6.2.5p8 makes `unsigned _BitInt(17)` the unsigned type corresponding to
`_BitInt(17)`. Without `-flto` GCC prints `2`, and so does the same test with
`int`/`unsigned int`. Every `_BitInt(N)` pair we tried fails (N = 8, 17, 64,
65, 128, 256).
In lto1, alias sets come from `gimple_get_alias_set` (gcc/gimple.cc). Its
signed/unsigned merge checks only `TREE_CODE (t) == INTEGER_TYPE`, so `unsigned
_BitInt(N)` gets its own alias set. `c_common_get_alias_set` handles
`BITINT_TYPE` as well. The LTRANS fre3 then folds the reload of `*p` to `1`.
Also fails with GCC 14.1, 14.2, 14.3, 15.1, 15.2 and 16.1 (x86_64).
Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.