The following simple program bug.cc is incorrectly compiled if the optimization level is greater than -O1. The code is a fragment of a much larger program which highlighted the problem. Attached are: bug.cc - source code result_O1.txt - (expected) results of program compiled with -O1 result_O3.txt - (erroneous) results of program compiled with -O3 bug_O1.s - Assembler code of program compiled with -O1 bug_O3.s - Assembler code of program compiled with -O3 --- bug.cc --- #include <stdlib.h> #include <stdio.h> void bug(unsigned int n) { int i; printf("n = %d\n", n); int shift = -1; for (i=0; ((i<10) && (shift < 0)) ; i++) { printf("i = %d\n", i); if ((1UL << i) == n) shift = i; } printf("n = %d, shift = %d\n", n, shift); if (shift < 0) abort(); } main() { bug(64); exit (0); } --- result_O1.txt --- n = 64 i = 0 i = 1 i = 2 i = 3 i = 4 i = 5 i = 6 n = 64, shift = 6 --- result_O3.txt n = 64 i = 0 n = 64, shift = -1 Abort (core dumped) --- bug_O1.s --- .file "bug.cc" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "n = %d\n" .LC1: .string "i = %d\n" .LC2: .string "n = %d, shift = %d\n" .text .align 4 .globl bug__FUi .type bug__FUi,@function bug__FUi: .LFB1: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: pushl %edi .LCFI2: pushl %esi .LCFI3: pushl %ebx .LCFI4: subl $20, %esp .LCFI5: movl 8(%ebp), %edi pushl %edi pushl $.LC0 .LCFI6: call printf movl $-1, %esi movl $0, %ebx addl $16, %esp .p2align 2 .L6: subl $8, %esp pushl %ebx pushl $.LC1 call printf movl $1, %eax movb %bl, %cl sall %cl, %eax addl $16, %esp cmpl %edi, %eax jne .L5 movl %ebx, %esi .L5: incl %ebx cmpl $9, %ebx jg .L4 testl %esi, %esi js .L6 .L4: subl $4, %esp pushl %esi pushl %edi pushl $.LC2 call printf addl $16, %esp testl %esi, %esi jns .L11 .LCFI7: call abort .p2align 2 .L11: leal -12(%ebp), %esp popl %ebx popl %esi popl %edi popl %ebp ret .LFE1: .Lfe1: .size bug__FUi,.Lfe1-bug__FUi .align 4 .globl main .type main,@function main: .LFB2: pushl %ebp .LCFI8: movl %esp, %ebp .LCFI9: subl $20, %esp .LCFI10: pushl $64 .LCFI11: call bug__FUi movl $0, (%esp) call exit .LFE2: .Lfe2: .size main,.Lfe2-main .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.0)" --- bug_O3.cc --- .file "bug.cc" .version "01.01" gcc2_compiled.: .section .rodata .LC0: .string "n = %d\n" .LC1: .string "i = %d\n" .LC2: .string "n = %d, shift = %d\n" .text .align 4 .globl bug__FUi .type bug__FUi,@function bug__FUi: .LFB1: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: pushl %esi .LCFI2: pushl %ebx .LCFI3: subl $8, %esp movl 8(%ebp), %esi pushl %esi pushl $.LC0 .LCFI4: call printf popl %eax popl %edx pushl $0 pushl $.LC1 call printf addl $12, %esp xorl %eax, %eax cmpl $1, %esi sete %al decl %eax movl $-1, %ebx andl %eax, %ebx pushl %ebx pushl %esi pushl $.LC2 call printf addl $16, %esp testl %ebx, %ebx jns .L11 .LCFI5: call abort .p2align 2 .L11: leal -8(%ebp), %esp popl %ebx popl %esi popl %ebp ret .LFE1: .Lfe1: .size bug__FUi,.Lfe1-bug__FUi .align 4 .globl main .type main,@function main: .LFB2: pushl %ebp .LCFI6: movl %esp, %ebp .LCFI7: subl $16, %esp .LCFI8: pushl $64 pushl $.LC0 .LCFI9: call printf popl %ecx popl %eax pushl $0 pushl $.LC1 call printf addl $12, %esp pushl $-1 pushl $64 pushl $.LC2 call printf addl $16, %esp .LCFI10: call abort .LFE2: .Lfe2: .size main,.Lfe2-main .ident "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.0)"
Thanks, looks like strength reduction bug (goes away with -fno-strength-reduce), reproduceable in current CVS gcc as well. Will try to debug it.
I hope I've fixed this in http://gcc.gnu.org/ml/gcc-patches/2000-11/msg01698.html Waiting for peer review now, if it is accepted into CVS gcc, it will make it into gcc-2.96-65.