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.

Reply via email to