Bug 8606 - GNAT floating point optimization bug
Summary: GNAT floating point optimization bug
Status: RESOLVED DUPLICATE of bug 323
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.2.1
: P3 normal
Target Milestone: ---
Assignee: Richard Kenner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2002-11-16 02:56 UTC by 166255
Modified: 2014-02-16 13:12 UTC (History)
3 users (show)

See Also:
Host: i386-linux
Target: i386-linux
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description 166255 2002-11-16 02:56:02 UTC
[ Reported to the Debian BTS as report #166255.
  Please CC 166255@bugs.debian.org on replies.
  Log of report can be found at http://bugs.debian.org/166255 ]

[rechecked with 3.2.1 prerelease]

The program gnat_bug3, shown below, contains two consecutive comparisons
of Guess and Guess_Low.  As can be seen from the program output, the
first comparison indicates that the two variables are not equal, while
the second indicates that they are equal.  Both comparisons should
produce the same result.

The problem only occurs if optimization is turned on.  Without the -O
option both comparisons indicate that the two variables are equal.

Based on my rather hazy understanding of Intel assembly code, it
appears that the code between L35 and L36 computes the value of
Guess and stores it in memory.  The GNAT documentation states that
code generated by the compiler assumes that the Intel FPU is in 80
bit mode.  Thus the store operation converts an 80 bit value to a
64 bit value.  The code then compares the value in the register (the
80 bit value) to Guess_Low.  This is incorrect, since the 80 bit
value in the register is not equal to the value of Guess.

The second comparison reads the value of Guess from memory, so it uses
the 64 bit value.

Note that the generated code would be correct if the FPU was set to
64 bit mode, so whether the bug is in the GCC back end or the GNAT
front end would seem to depend on whether the back end optimizations
are justified in assuming that the FPU is in 64 bit mode.
			       Kenneth Almquist



------------------------------ gnat_bug3.adb ------------------------------
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Long_Float_Text_IO; use Ada.Long_Float_Text_IO;
procedure Gnat_Bug3 is

    function Next_Value(Guess_Low, Guess_High : Long_Float;
                        Error_Low, Error_High : Long_Float)
                  return Long_Float is
        Ratio : Long_Float;
        Guess : Long_Float;
    begin
        Ratio := -Error_Low / (Error_High - Error_Low);
        if Ratio > 1.0 or Ratio < 0.0 then
            Put("bad ratio ");
            Put(Ratio, 1, 10, 0);
            Put(", error_high = ");
            Put(Error_High, 1, 10, 0);
            Put(", error_low = ");
            Put(Error_Low, 1, 10, 0);
            New_Line;
        end if;
        Ratio := Ratio * 0.99 + 0.005;
        Guess := Guess_Low + Ratio * (Guess_High - Guess_Low);
        if Guess = Guess_Low then
            Put_Line("First test:   Guess = Guess_Low");
        else
            Put_Line("First test:   Guess /= Guess_Low");
        end if;
        if Guess = Guess_Low then
            Put_Line("Second test:  Guess = Guess_Low");
        else
            Put_Line("Second test:  Guess /= Guess_Low");
        end if;
        return Guess;
    end Next_Value;

    Guess : Long_Float;

begin -- Gnat_Bug3

    Guess := Next_Value(9.07611839107694429, 9.07611839107696916,
                        -2.22044604925031308E-16, 1.96231919602496419E-14);

end Gnat_Bug3;


-------------- output from gnatmake gnat_bug3 -cargs -gnatv -O --------------
gcc-3.2 -c -gnatv -O gnat_bug3.adb

GNAT 3.2.1 20020912 (prerelease) Copyright 1992-2001 Free Software Foundation, Inc.

Compiling: gnat_bug3.adb (source file time stamp: 2002-10-23 17:53:11)
 43 lines: No errors
gnatbind -x gnat_bug3.ali
gnatlink gnat_bug3.ali


------------------------------ program output ------------------------------
First test:   Guess /= Guess_Low
Second test:  Guess = Guess_Low


----------------------- compiler output (gnat_bug3.s) -----------------------
	.file	"gnat_bug3.adb"
	.section	.rodata
	.align 4
LC3:
	.long	1
	.long	10
	.align 4
LC5:
	.long	1
	.long	15
	.align 4
LC7:
	.long	1
	.long	14
	.align 4
LC11:
	.long	1
	.long	31
	.align 4
LC13:
	.long	1
	.long	32
LC2:
	.ascii	"bad ratio "
LC4:
	.ascii	", error_high = "
LC6:
	.ascii	", error_low = "
	.align 32
LC10:
	.ascii	"First test:   Guess = Guess_Low"
	.align 32
LC12:
	.ascii	"First test:   Guess /= Guess_Low"
	.align 32
LC14:
	.ascii	"Second test:  Guess = Guess_Low"
	.align 32
LC15:
	.ascii	"Second test:  Guess /= Guess_Low"
	.section	.rodata.cst8,"aM",@progbits,8
	.align 8
LC8:
	.long	2061584302
	.long	1072672276
	.align 8
LC9:
	.long	1202590843
	.long	1064598241
	.text
	.align 2
	.type	gnat_bug3__next_value.0,@function
gnat_bug3__next_value.0:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$24, %esp
	movl	%ecx, -4(%ebp)
	fldl	32(%ebp)
	fsubl	24(%ebp)
	fdivrl	24(%ebp)
	fstpl	-16(%ebp)
	xorb	$-128, -9(%ebp)
	fld1
	fldl	-16(%ebp)
	fucom	%st(1)
	fnstsw	%ax
	fstp	%st(1)
	testb	$69, %ah
	sete	%dl
	fldz
	fucompp
	fnstsw	%ax
	testb	$69, %ah
	sete	%al
	orb	%al, %dl
	je	.L35
	subl	$8, %esp
	movl	$.LC2, %eax
	movl	$.LC3, %edx
	pushl	%edx
	pushl	%eax
	call	ada__text_io__put__4
	movl	$0, (%esp)
	pushl	$10
	pushl	$1
	pushl	-12(%ebp)
	pushl	-16(%ebp)
	call	ada__long_float_text_io__put__2
	addl	$24, %esp
	movl	$.LC4, %eax
	movl	$.LC5, %edx
	pushl	%edx
	pushl	%eax
	call	ada__text_io__put__4
	movl	$0, (%esp)
	pushl	$10
	pushl	$1
	pushl	36(%ebp)
	pushl	32(%ebp)
	call	ada__long_float_text_io__put__2
	addl	$24, %esp
	movl	$.LC6, %eax
	movl	$.LC7, %edx
	pushl	%edx
	pushl	%eax
	call	ada__text_io__put__4
	movl	$0, (%esp)
	pushl	$10
	pushl	$1
	pushl	28(%ebp)
	pushl	24(%ebp)
	call	ada__long_float_text_io__put__2
	addl	$20, %esp
	pushl	$1
	call	ada__text_io__new_line__2
	addl	$16, %esp
L35:
	fldl	-16(%ebp)
	fmull	.LC8
	faddl	.LC9
	fstpl	-16(%ebp)
	fldl	8(%ebp)
	fsubrl	16(%ebp)
	fmull	-16(%ebp)
	faddl	8(%ebp)
	fstl	-24(%ebp)
	fldl	8(%ebp)
	fxch	%st(1)
	fucompp
	fnstsw	%ax
	andb	$69, %ah
	xorb	$64, %ah
	jne	.L36
	subl	$8, %esp
	movl	$.LC10, %eax
	movl	$.LC11, %edx
	jmp	.L42
L36:
	subl	$8, %esp
	movl	$.LC12, %eax
	movl	$.LC13, %edx
L42:
	pushl	%edx
	pushl	%eax
	call	ada__text_io__put_line__2
	addl	$16, %esp
	fldl	-24(%ebp)
	fldl	8(%ebp)
	fxch	%st(1)
	fucompp
	fnstsw	%ax
	andb	$69, %ah
	xorb	$64, %ah
	jne	.L39
	subl	$8, %esp
	movl	$.LC14, %eax
	movl	$.LC11, %edx
	jmp	.L43
L39:
	subl	$8, %esp
	movl	$.LC15, %eax
	movl	$.LC13, %edx
L43:
	pushl	%edx
	pushl	%eax
	call	ada__text_io__put_line__2
	addl	$16, %esp
	fldl	-24(%ebp)
	leave
	ret
Lfe1:
	.size	gnat_bug3__next_value.0,.Lfe1-gnat_bug3__next_value.0
	.align 2
globl _ada_gnat_bug3
	.type	_ada_gnat_bug3,@function
_ada_gnat_bug3:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$8, %esp
	pushl	$1024858112
	pushl	$0
	pushl	$-1129316352
	pushl	$0
	pushl	$1075980024
	pushl	$-44000907
	pushl	$1075980024
	pushl	$-44000921
	movl	%ebp, %ecx
	call	gnat_bug3__next_value.0
	fstp	%st(0)
	leave
	ret
Lfe2:
	.size	_ada_gnat_bug3,.Lfe2-_ada_gnat_bug3
	.ident	"GCC: (GNU) 3.2.1 20020912 (Debian prerelease)"
--------------------------------------------------------------------------

Release:
3.2.1 (Debian) (Debian unstable)

Environment:
System: Debian GNU/Linux (unstable)
Architecture: i686
host: i386-linux
Configured with: /home/packages/gcc/3.2/gcc-3.2-3.2.1ds5/src/configure -v --enable-languages=c,c++,java,f77,proto,objc,ada --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.2 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-java-gc=boehm --enable-objc-gc i386-linux
Comment 1 Eric Botcazou 2003-05-13 06:10:07 UTC
Responsible-Changed-From-To: unassigned->kenner
Responsible-Changed-Why: Ada specialist. Richard, this bug is related to the very classical
    problem of the extra-precision of the x86 FPU. The "fix" for other
    languages is to pass "-ffloat-store" to the compiler. Is it valid
    for GNAT too?
Comment 2 Geert Bosch 2003-05-13 13:46:51 UTC
From: Geert Bosch <bosch@gnat.com>
To: gcc-prs@gcc.gnu.org, 166255@bugs.debian.org,
	kalmquist1@hotmail.com, kenner@gcc.gnu.org, gcc-bugs@gcc.gnu.org,
	gcc-gnats@gcc.gnu.org
Cc:  
Subject: Re: ada/8606: GNAT floating point optimization bug
Date: Tue, 13 May 2003 13:46:51 -0400

 Indeed the issue here is the standard one of double rounding for
 64-bit floating point types. There is nothing Ada-specific about
 this and these problems are identical in C. The -ffloat-store
 option may improve repeatability, but has two undesired effects:
 it degrades performance and it always causes double rounding,
 which can degrade accuracy.
 
 For numerical code that requires exact rounding, only use 32-bit
 or 80-bit floating point types. When you need an expression to
 be computed to exactly 32 bits without any excess precision,
 store it to a volatile variable.
 
 If you really need 64-bit types with exact rounding, you'll have
 to set the rounding mode accordingly, but this will need changes
 in the Ada run time to prevent it from using 80-bit types.
 
    -Geert
Comment 3 Florian Weimer 2003-05-27 20:03:31 UTC
The analysis in http://gcc.gnu.org/ml/gcc-bugs/2003-05/msg03134.html
indicates that this bug is not Ada-specific (I'm not sure if it's
x86-specific, technically speaking, though).
Comment 4 Geert Bosch 2003-06-13 14:31:03 UTC
As described earlier, varying accuracy on x86 depending on optimization is not a bug. A lot has 
been written about this over the years. Search the archives if you're interested. There is nothing to 
fix here.
Comment 5 Andrew Pinski 2003-07-06 19:20:13 UTC
Reopening bug so it can be marked as a dup of ...
Comment 6 Andrew Pinski 2003-07-06 19:20:25 UTC
bug 323, which is the master bug for excessive precision.

*** This bug has been marked as a duplicate of 323 ***
Comment 7 Jackie Rosen 2014-02-16 13:12:52 UTC Comment hidden (spam)