This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]