[prev in list] [next in list] [prev in thread] [next in thread] 

List:       gcc-bugs
Subject:    [Bug other/32172]  New: Behavior of -ffast-math
From:       "dominiq at lps dot ens dot fr" <gcc-bugzilla () gcc ! gnu ! org>
Date:       2007-05-31 20:39:16
Message-ID: bug-32172-12313 () http ! gcc ! gnu ! org/bugzilla/
[Download RAW message or body]

In http://gcc.gnu.org/ml/gcc-patches/2007-05/msg01931.html
Andrew Pinski wrote:

> On 5/28/07, Dominique Dhumieres <dominiq@lps.ens.fr> wrote:
> > So if I am not mistaken, -ffast-math does not obey the parentheses.
> > If you consider this is a bug, I'll fill a bug report.
> 
> -ffast-math enables -funsafe-math-optimizations which tells the
> compiler to ignore those rules (and reassiocate all it can).  So no
> this is not a bug.  This is by design.

In my opinion, this is a very bad design. Take the following code:

    real :: f1, f2
    print *, f1(1.2), f2(1.2)
    print *, f1(nearest(1.5,-1.0)), f2(nearest(1.5,-1.0))
    print *, f1(1.5), f2(1.5), anint(1.5)
    print *, f1(nearest(1.5,1.0)), f2(nearest(1.5,1.0))
    print *, f1(1.7), f2(1.7)
end
real function f1(a)
    real, parameter :: f = 2.0**23
    real :: a
    f1 = (f+a)-f
end
real function f2(a)
    real, parameter :: f = 2.0**23
    real :: a
    f2 = (a+f)-f
end

As you can try, f1(a) and f2(a) return anint(a) in a much faster way
(I borrowed the trick from xlf!-). -funsafe-math-optimizations prevents
me to use it with other "unsafe-math-optimizations" (see below why this 
can be bad).

For me one of the following actions should be taken (ranked according my 
preference):

(1) This feature should be deleted, though I have no illusion!
As a lazy programmer when I put parentheses I have good reasons (see the
above code) and want the parentheses obeyed as it is mandatory in Fortran.
To bad if it does not give a good timing on some stupid benchmark designed 
to test this kind of pseudo-optimisation.

(2) Remove the feature from -funsafe-math-optimizations and add a new 
option -fdont-obey-parentheses (anything like that) being not part of 
-ffast-math.

(3) Emit a warning when the parentheses are not obeyed.

(4) At least, document (in flashing bold-face red) the (mis)feature:

The gcc manual says:

> -funsafe-math-optimizations
> 
>     Allow optimizations for floating-point arithmetic that (a) assume
>     that arguments and results are valid and (b) may violate IEEE or ANSI
>     standards.  When used at link-time, it may include libraries or
>     startup files that change the default FPU control word or other
>     similar optimizations.
> 
>     This option is not turned on by any -O option since it can result in
>     incorrect output for programs which depend on an exact implementation
>     of IEEE or ISO rules/specifications for math functions.  It may,
>     however, yield faster code for programs that do not require the
>     guarantees of these specifications.
> 
>     The default is -fno-unsafe-math-optimizations. 

As far as I can read English, I do not see any mention of parentheses
removal in this quotation.  Note that (2), (3), and (4) are not
incompatible, but in any case (4) is mandatory in my opinion if (1) is
rejected.

Now consider this other code:

integer i, n
real a, b
n = 0
do i = 0, 999
   a = 0.001*real(i)
   b = real(i)/1000.0
   if ((a /= b) .and. (n == 0)) print *, a-b, spacing(a)
   if (a /= b) n = n + 1
   end do
   print *, n
end

compiled with "-O", it yields:

4.6566129E-10  4.6566129E-10
       584

'a' and 'b' are not equal, but differ only by the round-off error.
Now compiled with "-O -funsafe-math-optimizations", it yields:

0

Though I did not look at the assembly code, I am pretty sure that the
division by 1000.0 has been replaced by a multiplication by 1.0/1000.0
computed only once outside the loop.  Since the division is a very costly
operation this can give a significant speedup for some codes.  In my opinion,
this is a very useful optimization (should be included at some level of -O,
say -O3) and pretty safe.  Indeed one could argue that if I am really
interested by this optimization, I can always do it by hand.  My answer is
that in general I use it in my codes, but sometime the code is easier to
understand if the division is left where it belongs in the formulae and I
don't see why I'd have to chase divisions when I use the code from a
colleague.  In addition if the argument is true for division, it is also
for writing (a+f)-f if all what you want is a!

To summarize I do not see the logic of the design of
"-funsafe-math-optimizations": it mixes legitimate (and safe from a
numerical point of view) optimization with illegitimate (in the sense that
the code is no longer complying to the requirements of the programming
language) ones.

Final note (to document?): the division is optimized outside the loop with
"-funsafe-math-optimizations", while the parentheses are not obeyed
starting at "-O1 -funsafe-math-optimizations", but
"-O0 -funsafe-math-optimizations" obeys the parentheses.


-- 
           Summary: Behavior of -ffast-math
           Product: gcc
           Version: 4.3.0
            Status: UNCONFIRMED
          Severity: enhancement
          Priority: P3
         Component: other
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: dominiq at lps dot ens dot fr


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=32172

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic