C99 Pragmas
Support has been added for the three C99 standard pragmas:
#pragma STDC FENV_ACCESS (defaults to OFF)
#pragma STDC FP_CONTRACT (defaults to OFF)
#pragma STDC CX_LIMITED_RANGE (defaults to OFF)
Only FENV_ACCESS currently has any effect; with it off, the compiler can
assume that floating-point operations have no side-effects, and ignores any
possibility of exceptions or traps. With it on, care is taken to ensure that
all arithmetic occurs (as if) at run-time. For example
double fred(void)
{
return 1.0 / 3.0;
}
will compile to
fred
LDFD f0, =0.3333333333333333
MOV pc, lr
but
#include
double fred(void)
{
#pragma STDC FENV_ACCESS ON
return 1.0 / 3.0;
}
will compile to
fred
MVFD f0, #1
DVFD f0, f0, #3
MOV pc, lr
to ensure that the inexact flag gets set (and with a view to rounding mode
altering the result). The compiler will still fold expressions that can be
determined to raise no exceptions (eg 1.0 / 2.0). Compile-time evaluation can
also be forced thus:
double fred(void)
{
#pragma STDC FENV_ACCESS ON
static const double one_third = 1.0 / 3.0;
return one_third;
}
Other optimisations, particularly CSE, are effectively inhibited on
floating-point arithmetic if FENV_ACCESS is on.
In C90 mode, the compiler functions as before, and only considers
overflow, invalid operation and divide by zero exceptions as significant.
Thus 1.0 / 0.0 would be performed at run-time, but 1.0 / 3.0 would not.
For other optimisations, behaviour is somewhere in-between the two C99
states.
|