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.

Reply via email to