https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91475
Bug ID: 91475 Summary: Optimization causes infinite loop Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eric_musser at yahoo dot com Target Milestone: --- The following code on x86-64 9.2.0 compiled with: gcc -Wall -O2 unexpectedly produces wrong output and an infinite loop: #include <stdio.h> #include <iostream> int main(int argc, char** argv) { char buf[50]; for (int j = 0; j < 9; ++j) { std::cout << (j * 0x20000001) << " " << j << std::endl; sprintf(buf, "%d", j); } return 0; } Output (truncated) is: 0 0 536870913 1 1073741826 2 1610612739 3 -2147483644 4 -1610612731 5 -1073741818 6 -536870905 7 8 8 536870921 9 1073741834 10 1610612747 11 -2147483636 12 -1610612723 13 ... The sprintf is present only to prevent the loop from being unrolled (and the issue doesn't occur). The issue appears to because the code is being optimized roughly as: int main(int argc, char** argv) { char buf[50]; for (int j = 0, running_j = 0; running_j != 9 * 0x20000001LL ; running_j += 0x20000001, ++j) { std::cout << running_j << " " << j << std::endl; sprintf(buf, "%d", j); } return 0; } It loops because running_j is int32 and cannot possibly equal the pre-computed total. The optimizer actually detects this and removes the end condition of the for loop completely. I realize the code is invoking undefined behavior because of signed overflow with j * 0x20000001LL but it seems either the compiler should error/warning because of this or the for loop optimization should not happen. Without, the sprintf I do see a warning of undefined behavior (in loop iteration 4). I see other bugs similar to this but this is the only I see with a hardcoded constant as the end condition of the for loop.