https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124429
Bug ID: 124429
Summary: Incorrect code generation for pointer-to-array access
under -O2 on x86_64
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: xiongzile99 at gmail dot com
Target Milestone: ---
Created attachment 63865
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63865&action=edit
dumped ir code
The following program produces incorrect output when compiled with -O2 using
GCC 11.3 and newer on x86_64.
When compiled with -O1 the output is correct.
The program accesses a 2D array through a pointer-to-array type (int (*)[4]).
This appears to be well-defined C: the pointer `p` has type `int (*)[4]`, which
matches the type of `array` (`int[4][4]`), and the expression `*(*(p + i) + j)`
is equivalent to `p[i][j]`.
However with -O2 the generated code produces incorrect results.
Test case
---------
#include <stdio.h>
int main() {
int array[4][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}
};
int (*p)[4] = array;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
printf("%4d", *(*(p + i) + j));
}
printf("\n");
}
return 0;
}
Compile commands
----------------
gcc -O1 test.c
gcc -O2 test.c
Example reproduction:
gcc -O2 test.c && ./a.out
Expected output
---------------
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Observed result
---------------
With -O1 the output is correct.
With -O2 incorrect values are printed.
Version testing
---------------
The issue was reproduced with the following versions of GCC:
gcc 11.3.0 : incorrect output with -O2
gcc 12.x : incorrect output with -O2
gcc 13.x : incorrect output with -O2
The program produces correct output with:
gcc -O1 test.c
gcc -O2 -fno-strict-aliasing test.c
Additional observations
-----------------------
The issue disappears when disabling strict aliasing optimizations:
gcc -O2 -fno-strict-aliasing test.c
This suggests that the miscompilation may be related to alias analysis or a
later optimization pass relying on strict aliasing assumptions.
The program itself does not appear to violate the strict aliasing rules.
The pointer `p` has type `int (*)[4]`, which is compatible with the type of
`array` (`int[4][4]`), and the expression
*(*(p + i) + j)
is equivalent to
p[i][j]
which directly indexes the original array.
Comparison with other compilers
-------------------------------
The same program produces the correct output when compiled with Clang using the
same optimization level:
clang -O2 test.c
System information
------------------
Architecture: x86_64
Operating system: Linux
Compiler: gcc (Debian) 11.3.0
Full compiler version output:
gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/x86_64-linux-gnu/11.3.0/lto-wrapper
Target: x86_64-linux-gnu
Configured with: /usr/src/gcc/configure --build=x86_64-linux-gnu
--disable-multilib --enable-languages=c,c++,fortran,go
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 11.3.0 (GCC)
Notes
-----
The program does not trigger any warnings with:
gcc -O2 -Wall -Wextra -Wpedantic test.c
and does not appear to rely on undefined behavior.
The issue was observed on multiple x86_64 Linux systems.