https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119543
Bug ID: 119543 Summary: At -O1 and higher, GCC incorrectly optimizes isTmax function to always return 0 Product: gcc Version: 13.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: 2023152001 at email dot szu.edu.cn Target Milestone: --- Bug Description: When compiling with -O1 or higher optimization levels, GCC incorrectly optimizes a function that detects the maximum two's complement integer (Tmax, 0x7FFFFFFF) to always return 0, even for valid Tmax input. Steps to Reproduce: 1. Save the following code to isTmax_bug.c: int isTmax(int x) { int temp = x + 1; int tmin = 1 << 31; /* 0x80000000 - Minimum two's complement value */ int t = temp ^ tmin; int y = !t; return y; } int main() { /* Should print 1 for Tmax (0x7FFFFFFF) */ return isTmax(0x7FFFFFFF); } 2. Compile with -O0 (works correctly): gcc -m32 -O0 isTmax_bug.c -o isTmax_O0 3. Compile with -O1 (incorrect optimization): gcc -m32 -O1 isTmax_bug.c -o isTmax_O1 4. Run both programs: ./isTmax_O0 # Returns 1 (correct) ./isTmax_O1 # Returns 0 (incorrect) GCC Version Information: gcc version 13.3.0 (Ubuntu 13.3.0-6ubuntu2~24.04) Target: x86_64-linux-gnu Assembly Code Comparison: O0 optimization (correct): isTmax: pushl %ebp movl %esp, %ebp subl $16, %esp call __x86.get_pc_thunk.ax addl $_GLOBAL_OFFSET_TABLE_, %eax movl 8(%ebp), %eax addl $1, %eax movl %eax, -16(%ebp) movl $-2147483648, -12(%ebp) movl -16(%ebp), %eax xorl -12(%ebp), %eax movl %eax, -8(%ebp) cmpl $0, -8(%ebp) sete %al movzbl %al, %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax leave O1 optimization (incorrect): isTmax: movl $0, %eax ret Analysis: This bug appears to be related to how the compiler handles signed integer overflow. The function is designed to detect Tmax (0x7FFFFFFF) by checking if (x+1)^0x80000000 == 0, which is true only when x+1 == 0x80000000 (i.e., x is Tmax). When x is 0x7FFFFFFF (Tmax), x+1 causes signed overflow, producing 0x80000000 (Tmin). The compiler may incorrectly assume this overflow case never happens due to undefined behavior rules in C, leading to the wrong optimization of always returning 0. Temporary Workaround: Either compile with -O0 or use an alternative implementation: int isTmax(int x) { int y = ~(x+1); int t1 = !(x^y); int t2 = !!(x+1); return t1&t2; } This alternative implementation also detects Tmax correctly but avoids the optimization issue.