| Summary: | gcc optimiser bug with -O -march=i686 | ||
|---|---|---|---|
| Product: | Base System | Reporter: | peter.jeremy <peter.jeremy> |
| Component: | gnu | Assignee: | David E. O'Brien <obrien> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 5.0-CURRENT | ||
| Hardware: | Any | ||
| OS: | Any | ||
Responsible Changed From-To: freebsd-bugs->obrien David, would you please take care of this? On Thu, Nov 29, 2001 at 12:33:24AM -0800, ru@FreeBSD.org wrote: > Synopsis: gcc optimiser bug with -O -march=i686 > > Responsible-Changed-From-To: freebsd-bugs->obrien > Responsible-Changed-By: ru > Responsible-Changed-When: Thu Nov 29 00:32:54 PST 2001 > Responsible-Changed-Why: > David, would you please take care of this? Please also take a look at the recent thread in -hackers: Subject: add some constraints in cpufunc.h Message-ID: <00e701c17264$a4617130$ef01a8c0@davidwnt> G'luck, Peter -- This sentence contradicts itself - or rather - well, no, actually it doesn't! State Changed From-To: open->closed Would you mind checking whether this still applies, and if it does, report the problem to the GCC developers using http://gcc.gnu.org/cgi-bin/gnatsweb.pl? I'm sorry I hadn't noticed this earlier, but it seems the problem has been solved with the rewrite of the i386 backend for GCC 3.x? .file "x.c" .section .rodata.cst4,"aM",@progbits,4 .align 4 .LC0: .long 1069547520 .text .globl bar .type bar, @function bar: pushl %ebp movl %esp, %ebp subl $24, %esp cmpl $0, x je .L2 flds .LC0 jmp .L3 .L2: fld1 .L3: fstpl 8(%esp) cmpl $0, x je .L4 flds .LC0 jmp .L5 .L4: fld1 .L5: fstpl (%esp) call foo movl %ebp, %esp popl %ebp ret .size bar, .-bar .comm x,4,4 .ident "GCC: (GNU) 3.3 20030429 (prerelease)" |
gcc generates incorrect code for the program below when compiled with options "-O -march=i686". The problem appears to be an incorrect assumption in gcc/config/i386/i386.c:notice_update_cc() which assumes that moves don't affect condition codes. The double arguments are passed using movdf_push, but the IA32 doesn't have a floating point push, so this is implemented as a store followed by a stack pointer adjustment - which does affect CC. Changing all the floating point constants/arguments to integer removes the bug. This showed up building the gnuplot port. I don't know if it affects anything in the base system. Fix: Not known at this time. How-To-Repeat: Save the following code as x.c and compile with "/usr/libexec/cc1 -O -march=i686 -quiet x.c" --- int x; void foo(double, double); void bar() { foo(x?1.5:1.0, x?1.5:1.0); } --- This results in the following assember (annotations added by me): --- .file "x.c" .version "01.01" gcc2_compiled.: .section .rodata .p2align 3 .LC0: .long 0x0,0x3ff80000 .text .p2align 2,0x90 .globl bar .type bar,@function bar: pushl %ebp movl %esp,%ebp subl $8,%esp fld1 movl x,%eax fldl .LC0 fld %st(1) testl %eax,%eax <-- this is the "x?" part of the code. fcmovne %st(1),%st subl $8,%esp <-- this destroys CC from the above testl fstpl (%esp) fcmove %st(1),%st <-- this assumes the testl CC is still valid fstp %st(1) subl $8,%esp fstpl (%esp) call foo movl %ebp,%esp popl %ebp ret .Lfe1: .size bar,.Lfe1-bar .comm x,4,4 .ident "[ASM_FILE_END]GCC: (c) 2.95.3 20010315 (release)" ---