This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: FENV_ACCESS questions in C and Fortran
> Date: Wed, 10 Nov 1999 09:50:14 -0500 (EST)
> From: Stephen L Moshier <moshier@mediaone.net>
> Reply-To: moshier@mediaone.net
> cc: gcc@gcc.gnu.org
>
>
> If you could point out where the standard gives pertinent
> information on the code hoisting question, that would be very
> helpful. I find statements like the following, that seem to
> speak against the behaviors that you were advocating.
The basic rule is the "as if" rule. A compiler may do any
transformation on a strictly conforming program so long as the program
behaves as if those transformations are not done.
> Floating-point operations implicitly
> set the status flags; modes affect result values of
> floating-point operations. Implementations that support
> such floating-point state are required to regard changes
> to it as side effects -- see annex F for details. The
> floating-point environment library <fenv.h> provides a
> programming facility for indicating when these side
> effects matter, freeing the implementations in other
> cases.
A "side effect" for our purposes is a change to the visible state of
the abstract machine.
For instance, in the expression
x++
the change to the value of 'x' is a side effect. (The real operation
is the returning of the value of `'x').
However, if a program has
x++;
x++;
then the compiler does not need to increment 'x' twice. It can deduce
that the value of 'x' is not used after the first increment, and turn
this into
x += 2;
(assuming that 'x' is not volatile and is an integer type).
A similar optimisation is possible with the fp-env flags. If a
program has
#pragma STDC FENV_ACCESS ON
float z;
...
z = 10.0 * 0.1;
z = 10.0 * 0.1;
then the first computation can go away altogether, because the
compiler can deduce that the status flags and 'z' will be set
correctly even if only the second computation is made, and neither the
flags nor the value of 'z' are examined between the two statements.
> [#2] The FENV_ACCESS pragma provides a means to inform the
> implementation when a program might access the floating-
> point environment to test flags or run under non-default
> modes.163)
The importance of the FENV_ACCESS pragma is that if the program does
not use it (or explicitly turns it off), the compiler can assume:
- The rounding mode is the default
- The status flags are not tested.
For instance, in the following:
float foo(void)
{
return 10.0 * 0.1;
}
with FENV_ACCESS off, the compiler can convert this to a simple return
of a constant. With FENV_ACCESS on, the compiler cannot because it
does not know the rounding mode and because the routine will set the
INEXACT flag.
> 163The purpose of the FENV_ACCESS pragma is to allow certain
> optimizations, for example global common subexpression
> elimination, code motion, and constant folding, that
> could subvert flag tests and mode changes.
Another example here is the following:
float foo(float x, float y)
{
if (x > y)
return x * 0.1;
else
return x;
}
without FENV_ACCESS, the compiler can do:
float foo(float x, float y)
{
float b;
b = x * 0.1;
return x > y ? b : x;
}
which is likely to be faster, for instance on powerpc the 'return'
statement is a single instruction. But the compiler cannot do this if
FENV_ACCESS is set, because the caller might examine the status flags
after the routine and expect that they have changed only if x > y.
--
Geoffrey Keating <geoffk@cygnus.com>