I believe what is happening is that a loop like for (int i = 1; i; ++i) { int64_t m = i * CONST_LL ...}
is being optimized to roughly: int64_t m = 0; for (...) { m += CONST_LL ...} My code was intentionally allowing i to become negative (it was testing the equivalence of two expressions for all int i except 0). If the multiply really happens, when i wraps around 'm' becomes negative. In the optimized version it keeps growing as if it were 'unsigned int i'. The simplified repro case included can be "fixed" by changing the initial 'int i = 1' to 'int i = -10'. Also for some reason the 'm2' test (greatly simplified from the original code) cannot be removed without "fixing" the problem. And it does not occur without optimization: $ cc -O2 -o gccbug gccbug.c --save-temps -v Using built-in specs. Target: amd64-undermydesk-freebsd Configured with: FreeBSD/amd64 system compiler Thread model: posix gcc version 4.2.1 20070719 [FreeBSD] /usr/libexec/cc1 -E -quiet -v -D_LONGLONG gccbug.c -O2 -fpch-preprocess -o gccbug.i ignoring duplicate directory "/usr/include" #include "..." search starts here: #include <...> search starts here: /usr/include End of search list. /usr/libexec/cc1 -fpreprocessed gccbug.i -quiet -dumpbase gccbug.c -auxbase gccbug -O2 -version -o gccbug.s GNU C version 4.2.1 20070719 [FreeBSD] (amd64-undermydesk-freebsd) compiled by GNU C version 4.2.1 20070719 [FreeBSD]. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=102400 Compiler executable checksum: 2117630c4ec5f0cc97737a66d6c5822c gccbug.c: In function 'main': gccbug.c:24: warning: incompatible implicit declaration of built-in function 'printf' /usr/bin/as -V -Qy -o gccbug.o gccbug.s GNU assembler version 2.15 [FreeBSD] 2004-05-23 (x86_64-obrien-freebsd) using BFD version 2.15 [FreeBSD] 2004-05-23 /usr/bin/ld --eh-frame-hdr -V -dynamic-linker /libexec/ld-elf.so.1 -o gccbug /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib -L/usr/lib gccbug.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtend.o /usr/lib/crtn.o GNU ld version 2.15 [FreeBSD] 2004-05-23 Supported emulations: elf_i386_fbsd elf_x86_64_fbsd # 1 "gccbug.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "gccbug.c" typedef long long int int64_t; typedef unsigned long int uint32_t; # 12 "gccbug.c" int main() { int i = 0; for (i = 1; i; ++i) { int64_t m = i * 16807LL; uint32_t m2 = 8; if (i == -2 && m2 != 7) printf("%d (%lld)\n", i, m); } } When it fails: $ ./gccbug -2 (72185515310258) Correct output would be -2 (-33614) -- Summary: reduction of in-loop 64-bit multiply to repeated add wrong when loop var wraps neg Product: gcc Version: 4.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: rtl-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: ben at ben dot com GCC build triplet: amd64-undermydesk-freebsd GCC host triplet: amd64-undermydesk-freebsd GCC target triplet: amd64-undermydesk-freebsd http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39338