https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120607
Bug ID: 120607
Summary: Incorrect optimization of multiple
__builtin_unreachable() conditions leads to logic
errors in control flow
Product: gcc
Version: 15.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: 2023091106 at cauc dot edu.cn
Target Milestone: ---
this problems exist in X86_64 gcc13/14/15。
GCC exhibits incorrect optimization behavior when handling multiple (>2)
__builtin_unreachable() statements.
When only a single __builtin_unreachable() is used, or when compiling with -O0,
the code executes correctly. However, when two or more __builtin_unreachable()
statements are present, the program behaves correctly under -O0, but under -O2,
GCC incorrectly folds the entire test_builtin_unreachable() function, leading
to an infinite loop at runtime.
This suggests that the optimizer does not correctly account for the
interactions of multiple unreachable paths during optimization.
========the gcc code========
#include <stdio.h>
#include <stdlib.h>
void test_output() {
printf("the code is executing\n");
}
void test_builtin_unreachable() {
int bb = 2;
if ((bb & ~3) != 0)
__builtin_unreachable();
if ((bb & 1) == 0)
__builtin_unreachable();
if (bb == 2)
printf("the value of bb is: %d\n", bb);
}
int main() {
test_output();
test_builtin_unreachable();
return 0;
}
========the gcc output========
$ gcc -O0 test.c -o testclear
$ ./test
the code is executing
the value of bb is: 2
$ gcc -O2 test.c -o test
$ ./test
the code is executing
the code is executing
the code is executing
……
the code is executing
the code is executing
the code is executing
Segmentation fault (core dumped)
========the gcc versions=========
$ gcc-14 -v
Using built-in specs.
COLLECT_GCC=gcc-14
COLLECT_LTO_WRAPPER=/opt/gcc-14/libexec/gcc/x86_64-pc-linux-gnu/14.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure --prefix=/opt/gcc-14 --enable-languages=c,c++
--disable-multilib
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 14.1.0 (GCC)
========the assembly code=========
when use the -O2, we can see the function test_builtin_unreachable is none, so
the test_output always be executing:
test_output:
lea rdi, [rip + .Lstr]
jmp puts@PLT
test_builtin_unreachable:
main:
push rax
lea rdi, [rip + .Lstr]
call puts@PLT
.Lstr:
.asciz "the code is executing"