https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120596

            Bug ID: 120596
           Summary: Wrong code on -O2 and above (possibly affecting many
                    versions)
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: ipa
          Assignee: unassigned at gcc dot gnu.org
          Reporter: haoxintu at gmail dot com
  Target Milestone: ---

Hi,

We found a possible wrong-code issue with our new testing tool. Please look at
the details below.

$cat small.c
#include <stdio.h>
#include <stdint.h>
static inline int8_t safe_mod_func_int8_t_s_s(int8_t si1, int8_t si2) {
    if (si2 == 0 || (si1 == INT8_MIN && si2 == -1))
        return si1;
    else
        return si1 % si2;
}

int idx = 0;
void __attribute__((noinline)) marker_1(void) { idx++;  printf("%d\n", idx); }

int32_t f = 0;
union {
  int64_t d;
  int32_t e;
} aa = {6};
struct {
  int32_t g;
} m[1][2] = {{{0}, {0}}};
int32_t k, l, j, i;
static int32_t *o = &aa.e;
int8_t n;
int64_t q[10][3] = {{0}};
int8_t r(int8_t *, int8_t *, int8_t *, uint32_t, uint32_t);
int8_t *ac(int8_t);
uint32_t ae(int8_t, int32_t *, int32_t *, int64_t);
static uint8_t af(void) {
  int8_t *ag = 0;
  int32_t ah = f;
  r(ag, ac(7), ag, ah, 0);
  return l;
}
int8_t r(int8_t *ai, int8_t *aj, int8_t *ak, uint32_t a, uint32_t am) {
an : {
  uint64_t ao = 3;
  int64_t *ap = &aa.d;
  *ap = 0;
  if (*o) {
    int32_t aq = 2;
    if (safe_mod_func_int8_t_s_s(m[0][1].g == (*aj = aq) == 0, ao))
      marker_1();
    else
      goto an;
  }
}
  return (int8_t) q[6][2];
}
int8_t *ac(int8_t as) {
  int32_t *at[10][10] = {&f};
  int8_t *au = &n;
  ae(0, at[5][6], &k, 3);
  return au;
}
uint32_t ae(int8_t c, int32_t *d, int32_t *e, int64_t bg) {
  for (; k >= 0;)
    return j;
  for (;; n--)
    o = &i;
}
int main(void) { f = 100; af(); }

$gcc-trunk -w -std=c99 -O0 small.c -o t0 ; ./t0


$gcc-trunk -w -std=c99 -O1 small.c -o t1 ; ./t1


$gcc-trunk -w -std=c99 -O2 small.c -o t2 ; ./t2
1

$gcc-trunk -w -std=c99 -O3 small.c -o t3 ; ./t3
1

The behavior in the Compcert compiler.

$ccomp -w -std=c99 -O0 small.c -o t-c0 ; ./t-c0

$ccomp -w -std=c99 -O small.c -o t-c1 ; ./t-c1

The version I used:

$gcc-trunk -v
Using built-in specs.
COLLECT_GCC=gcc-trunk
COLLECT_LTO_WRAPPER=/home/haoxin/research/gcc/build/libexec/gcc/x86_64-pc-linux-gnu/16.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --prefix=/home/haoxin/research/gcc/build
--enable-bootstrap --enable-checking=release --enable-languages=c,c++
--enable-multilib --program-suffix=-trunk : (reconfigured) ../configure
--prefix=/home/haoxin/research/gcc/build --enable-bootstrap
--enable-checking=release --enable-languages=c,c++ --enable-multilib
--program-suffix=-trunk : (reconfigured) ../configure
--prefix=/home/haoxin/research/gcc/build --enable-bootstrap
--enable-checking=release --enable-multilib --program-suffix=-trunk
--enable-languages=c,c++,lto --no-create --no-recursion
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 16.0.0 20250607 (experimental) (GCC) 


$ccomp --version
The CompCert C verified compiler, version 3.15

Reproduced in Godblot: https://godbolt.org/z/KEo5nah7f. Many old versions of
GCC behave the same.

Interestingly, the LLVM compiler also behaves the same as GCC, so I am unsure
if this code contains any UB (I checked the code carefully and am not aware of
any). Since CompCert (a formally verified C compiler) behaves consistently with
different optimization levels, I doubt there is something wrong with GCC (and
LLVM). Could you please have a look and let me know if I've missed anything?
Thanks!


Best regards,
Haoxin

Reply via email to