[comp.compilers] Optimizing IEEE Floating-Point Operations

daryl@hpclopt.cup.hp.com (06/06/91)

Suppose I have a program with the following statements:

            x = 0.0;     /* statement A */

            y = y * x;   /* statement B */

Let us assume that x and y are floating-point variables and that the
underlying machine uses the IEEE floating-point representation.  Assuming
that we can determine that x does not change between A and B, should the
expression (y * x) in statement B be replaced with 0.0?  What if y is a NaN?
(A constant propagation pattern like this occurs in the tomcatv SPEC
benchmark.)

The PA-RISC compilers do not currently perform this transformation because it
makes conservative assumptions about the programmer's desire to adhere to the
IEEE standard.

What do compilers from other vendors (besides HP) do by default?  Are any
options provided to override the default?  Does anyone have an opinion on
what the right thing to do is?

Thanks,
Daryl Odnert            daryl@hpclopt.cup.hp.com
Hewlett-Packard
California Language Lab
[There currently is a heated argument in comp.arch on this point, with much of
the problem being that the IEEE FP standard and the various language standards
talk past each other, leaving large grey areas. -John]
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

bron@sgi.com (Bron Campbell Nelson) (06/12/91)

Daryl Odnert (daryl@hpclopt.cup.hp.com) writes:
>             x = 0.0;     /* statement A */
>             y = y * x;   /* statement B */
> Let us assume that x and y are floating-point variables and that the
> underlying machine uses the IEEE floating-point representation.  Assuming
> that we can determine that x does not change between A and B, should the
> expression (y * x) in statement B be replaced with 0.0?  What if y is a NaN?

My own *personal* opinion is that this is a legal transformation if and
only if the runtime system traps (and aborts) on generation of NaN's and
Inf's.  For example, the Fortran standard clearly states that an expression
may be replaced by one that is "mathematically equivalent" but without
specifing just what kind of "mathematics."  If your particular mathematical
model includes NaN's and Inf's (e.g. the IEEE model), then this transformation
is NOT strictly legal, since the expressions are not always equivalent.
On the other hand, if your mathematical model does not have things like
NaN's and Inf's (i.e. the program blows up if such numbers are produced)
then the transformation IS legal.

Probably the "right" thing to do is to add yet another compiler option
and support both the "strict IEEE" and "intuitive" models.  Just my $0.02

--
Bron Campbell Nelson
Silicon Graphics, Inc.
2011 N. Shoreline Blvd.
Mtn. View, CA  94039
bron@sgi.com
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

bill@hcx2.SSD.CSD.HARRIS.COM (Bill Leonard) (06/14/91)

In article <91-06-011@comp.compilers>, bron@sgi.com (Bron Campbell Nelson) writes:
> My own *personal* opinion is that this is a legal transformation if and
> only if the runtime system traps (and aborts) on generation of NaN's and
> Inf's.  For example, the Fortran standard clearly states that an expression
> may be replaced by one that is "mathematically equivalent" but without
> specifing just what kind of "mathematics."  If your particular mathematical
> model includes NaN's and Inf's (e.g. the IEEE model), then this transformation
> is NOT strictly legal, since the expressions are not always equivalent.
> On the other hand, if your mathematical model does not have things like
> NaN's and Inf's (i.e. the program blows up if such numbers are produced)
> then the transformation IS legal.

As far as I know, there is only _one_ kind of mathematics.  The FORTRAN
standard is referring to real mathematics, not any particular means of
_approximating_ mathematics.  Under that rule, the transformation is
perfectly legal.  NaNs and INFs represent a failure of the machine model to
adequately represent the _mathematical_ result (i.e., the result you would
get with infinite precision).  In that sense, the IEEE standard is
(sometimes) mandating an answer that is mathematical nonsense, since the
answer would actually be zero if the machine had been able to accurately
represent the other operand.  (One exception to this is an INF operand that
was generated by a division by zero, as opposed to division by a very small
number.  In that case, you have 0/0, which is mathematically undefined.)

Our compilers, I believe, would perform the transformation.  As a general
rule, we take the view that NaNs and INFs are exceptional conditions,
rather than the norm.  There may be applications where that view is
incorrect, but so far we've not encountered them.

-- 
Bill Leonard
Harris Computer Systems Division
2101 W. Cypress Creek Road
Fort Lauderdale, FL  33309
bill@ssd.csd.harris.com
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

eggert@twinsun.com (Paul Eggert) (06/14/91)

	[... the IEEE FP standard and the various language standards
	talk past each other, leaving large grey areas. -John]

It's worse than that -- sometimes the standards flatly contradict each other.
E.g. IEEE 754 says that if you print -0 and read it back in again, you should
get -0, not 0; Fortran says that you can't tell the differences between
printing -0 and 0.  Luckily these cases are few; in practice IEEE 754 loses
these battles.

However, when IEEE 754 says ``the implementation must do A'' and a language
standard says ``the implementation is free to do either A or B'',
implementers desiring high performance sometimes improperly take the latter
statement as a license to do B while claiming support for IEEE arithmetic.
As a programmer, sometimes I prefer performance, but usually I prefer
standard, repeatable arithmetic.  A good compromise is for implementers to
have a compiler option like `-fast-but-loose' that means ``don't bother to
obey IEEE 754 exactly, just make it run fast.''  Clearly optimizing 0.0*X to
X falls in the fast-but-loose category in an IEEE environment where X might
be a NaN.  Some implementers might get by with supporting only the
fast-but-loose semantics, but if so I hope they don't pretend that they
conform to IEEE 754.

Unfortunately, new standards continue to be developed with equally large grey
areas.  E.g. a proposed international standard called LCAS aims to provide a
language-independent standard for computer arithmetic, but it ignores all
issues of NaNs, Infinities, -0, etc.

In a more hopeful development, the NCEG group is considering a standard for
IEEE 754 support for Standard C.  Let's hope they address the 0*X issue!
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

cfarnum@valhalla.cs.wright.edu (Charles Farnum) (06/17/91)

In article <91-06-016@comp.compilers>, bill@hcx2.SSD.CSD.HARRIS.COM
(Bill Leonard) writes:

]In article <91-06-011@comp.compilers>, bron@sgi.com (Bron Campbell
Nelson) writes:
]> ...For example, the Fortran standard clearly states that an expression
]> may be replaced by one that is "mathematically equivalent" but without
]> specifing just what kind of "mathematics." ...
]As far as I know, there is only _one_ kind of mathematics.  The FORTRAN
]standard is referring to real mathematics, not any particular means of
]_approximating_ mathematics.

There are many different mathematical systems.  Some happen to have operators
that are much easier to work with efficiently, or even effectively, than
others.  The IEEE standard is one such, and the best one available in the
eyes of most of the people who study such things.  Keep in mind that Kahan's
contributions to the standard helped win a Turing Award.  And Kahan is *not*
an ivory-tower academic; he is most emphatically interested in the real use
of computers for number crunching.

]Our compilers, I believe, would perform the transformation.  As a general
]rule, we take the view that NaNs and INFs are exceptional conditions,
]rather than the norm.  There may be applications where that view is
]incorrect, but so far we've not encountered them.

There are many applications *in principle* where that view is incorrect.
There are not many in practice because most computer scientists know very
little about writing code that is robust in the presence of NaNs and INFs.
This is primarily a problem of education, not of the difficulty of writing
such code.

I would steer clear of compilers that make such transformations; performing
algebraic manipulations valid in one mathematical system for some
computations to be performed in another mathematical system is dangerous.
Although I agree that they agree with the F77 standard (which is ambiguous on
the point, hardly avoidable given the different mathematical systems in
common use on computers in 1977), they can break well-written (i.e.,
efficient, readable, and robust) code that makes use of the provisions of the
IEEE standard.

  /charlie
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

henry@zoo.toronto.edu (Henry Spencer) (06/18/91)

In article <91-06-016@comp.compilers> bill@hcx2.SSD.CSD.HARRIS.COM (Bill Leonard) writes:
>As far as I know, there is only _one_ kind of mathematics...

Sorry, that view has been obsolete for a century, ever since non-Euclidean
geometry started being taken seriously.  You choose whichever mathematical
system is suited to the problems you want to tackle.  It is not at all
difficult to find extended versions of the real numbers which feature things
like infinities as part of the number system.  In fact, if you start looking
at the extended-real-number systems used in things like non-standard
analysis, you find "numbers" much stranger than anything in IEEE arithmetic.

>... NaNs and INFs represent a failure of the machine model to
>adequately represent the _mathematical_ result (i.e., the result you would
>get with infinite precision)...

Um, what *is* the "mathematical result" of, say, 1/0?  Even in high-school
mathematics, that's illegal, i.e. NaN.  In mathematical systems like the one
underlying IEEE arithmetic, it is +infinity.  There is no approximation
involved; either one is an exact, mathematically correct result that would
not be affected in any way by use of infinite precision.  Which is right, and
whether NaN is a representable value or simply results in an immediate
failure, depends on the number system in use.

It is important to realize that IEEE arithmetic is based on a slightly more
sophisticated view of the numerical world than that taught in high school,
and its implications cannot be understood in terms of high-school
mathematics.

It is also important to realize that you *cannot* reconcile the FORTRAN
standard with the IEEE arithmetic standard just by reading between the lines
intensively.  Actual changes to FORTRAN would probably be needed to make it
consistent with IEEE arithmetic.
-- 
Henry Spencer @ U of Toronto Zoology, henry@zoo.toronto.edu  utzoo!henry
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.

jbc@hpcupt3.cup.hp.com (Jeff Caldwell) (06/20/91)

> My own *personal* opinion is that this is a legal transformation if and
> only if the runtime system traps (and aborts) on generation of NaN's and
> Inf's.  

This sounds like a good idea but raises another question.  How about
a sequence such as:

    x = 0.0

    w = x * (y / z)

    where z ends up with the value of 0 at runtime.  

If this were allowed to become folded to a value of 0 at compile-time, the
calculation of y/z would never be performed.  Since y/z would have been
an invalid operation but has been removed, the runtime trap would never 
occur.

I feel the offering of an _option_ that allows the compiler to perform
transformations that may result in missing traps such as this is a
good approach.  The idea being that the user can stress test an application
until he is fairly sure it is robust enough to catch invalid operations
such as this before they occur.  Then he can use the option to build a
highly optimized production version of the application.

		-Jeff Caldwell | HP Calif. Lang. Lab
-- 
Send compilers articles to compilers@iecc.cambridge.ma.us or
{ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.