https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120578
Bug ID: 120578 Summary: Loop termination check eliminated under -O2/-O3/Os when int overflow occurs 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: --- in gcc11/12/13/14/15,When using optimization flags such as -O2, -O3, or -Os, the program may fall into an infinite loop. Upon inspecting the generated assembly code, the cmp and jl (compare and jump) instructions are missing, indicating that the condition i < 10 has been optimized away by the compiler. However, adding a branch like if (i == 2), or changing value += i * k to value += (long long)i * k, causes the program to execute correctly. This suggests that under these optimization levels, GCC performs early evaluation of arithmetic expressions and assumes int as the default type. This behavior results in the for loop’s termination condition being affected by internal computations, violating the Semantic Preservation Principle. Until a more appropriate constraint relationship is established, such optimizations should be avoided, especially when internal calculations can interfere with loop bounds. ========the gcc code======== #include <stdio.h> #include <stdlib.h> int main() { int value=0; int k = 1024*1024*1024; for (int i = 0; i < 10; i++) { if (i == 3){ // when set if (i ==2), the code will work normal break; } value += i * k; printf("i: %d\n", i); } return value; } ========the gcc output======== when use -O2/O3/Os, the code won't stop $ gcc -Wall -Wextra -O0 -o test test.c $ ./test i: 0 i: 1 i: 2 $ gcc-14 -Wall -Wextra -O2 -o test test.c $ ./test i: 0 i: 1 i: 2 i: 3 ... ========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 -O2/O3/Os, the cmp and jl (compare and jump) instructions are missing $in -O0 .LC0: .string "i: %d\n" main: push rbx mov ebx, 0 .L2: mov esi, ebx mov edi, OFFSET FLAT:.LC0 mov eax, 0 call printf add ebx, 1 cmp ebx, 3 je .L4 cmp ebx, 9 jle .L2 .L4: mov eax, 0 pop rbx ret $in -O2 .LC0: .string "i: %d\n" main: push rbx xor ebx, ebx .L2: mov esi, ebx mov edi, OFFSET FLAT:.LC0 xor eax, eax add ebx, 1 call printf jmp .L2