Package: gnat-3.2
Version: 1:3.2.1-0pre2

Operating system kernel version: Linux 2.4.17
CPU: Intel i686

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)"
--------------------------------------------------------------------------


Reply via email to