This is the mail archive of the fortran@gcc.gnu.org mailing list for the GNU Fortran project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Implement C _FloatN, _FloatNx types [version 6]


On Fri, Aug 19, 2016 at 04:23:55PM +0000, Joseph Myers wrote:
> On Fri, 19 Aug 2016, Szabolcs Nagy wrote:
> 
> > On 17/08/16 21:17, Joseph Myers wrote:
> > > Although there is HFmode support for ARM and AArch64, use of that for
> > > _Float16 is not enabled.  Supporting _Float16 would require additional
> > > work on the excess precision aspects of TS 18661-3: there are new
> > > values of FLT_EVAL_METHOD, which are not currently supported in GCC,
> > > and FLT_EVAL_METHOD == 0 now means that operations and constants on
> > > types narrower than float are evaluated to the range and precision of
> > > float.  Implementing that, so that _Float16 gets evaluated with excess
> > > range and precision, would involve changes to the excess precision
> > > infrastructure so that the _Float16 case is enabled by default, unlike
> > > the x87 case which is only enabled for -fexcess-precision=standard.
> > > Other differences between _Float16 and __fp16 would also need to be
> > > disentangled.
> > 
> > i wonder how gcc can support _Float16 without excess
> > precision.
> > 
> > using FLT_EVAL_METHOD==16 can break conforming c99/c11
> > code which only expects 0,1,2 values to appear (and does
> > not use _Float16 at all), but it seems to be the better
> > fit for hardware with half precision instructions.
> 
> Maybe this indicates that -fexcess-precision=standard, whether explicit or 
> implies by a -std option, must cause FLT_EVAL_METHOD=0 for such hardware, 
> and some new -fexcess-precision= option is needed to select 
> FLT_EVAL_METHOD=16 (say -fexcess-precision=16, with no expectation that 
> most numeric -fexcess-precision= arguments are supported except where a 
> target hook says they are or where they are the default FLT_EVAL_METHOD 
> value).

That seems reasonable for -fexcess-precision=standard and where it is
implied by a -std=c?? option.

My concern with this is that the use of comparisons of FLT_EVAL_METHOD
against 0 that Szabolcs is referring to is common and can have performance
implications. In glibc for example, 

  static FLOAT
  overflow_value (int negative)
  {
    __set_errno (ERANGE);
  #if FLT_EVAL_METHOD != 0
    volatile
  #endif
    FLOAT result = (negative ? -MAX_VALUE : MAX_VALUE) * MAX_VALUE;
    return result;
  }

The effect of setting FLT_EVAL_METHOD = 16 for -fexcess-precision=fast (which
is the default) would be to introduce additional "volatile" qualifiers,
which is probably not what the user intends. Elsewhere (quick search of the
debian code archive) the effect is to introduce more complicated assignment
routines or (in Boost's math/tr1.hpp) to define float_t and double_t:

  #if !defined(FLT_EVAL_METHOD)
  typedef float float_t;
  typedef double double_t;
  #elif FLT_EVAL_METHOD == -1
  typedef float float_t;
  typedef double double_t;
  #elif FLT_EVAL_METHOD == 0
  typedef float float_t;
  typedef double double_t;
  #elif FLT_EVAL_METHOD == 1
  typedef double float_t;
  typedef double double_t;
  #else
  typedef long double float_t;
  typedef long double double_t;
  #endif

It seems to me that if I set FLT_EVAL_METHOD = 16, I'm opening the AArch64
port to a number of performance issues in floating-point code if a user
has configured --with-arch=armv8.2-a+fp16 .

On the other hand, it would be unfortunate if _Float16 could not use the
ARMv8.2-A floating-point arithmetic instructions where they were available.

> Then -std=c2x, if C2X integrates TS 18661-3, might not imply the 
> value 0 for such hardware, because the value 16 would also be OK as a 
> standard value in that case.  This can be part of the design issues to 
> address alongside those I mentioned in 
> <https://gcc.gnu.org/ml/gcc-patches/2016-07/msg01899.html>.

I'm working on these. Right now, I have AArch64 set up as so:

If ARMv8.2-A extensions are available,

  -fexcess-precision=standard -> FLT_EVAL_METHOD = 0
  -fexcess-precision=fast -> FLT_EVAL_METHOD = 16

If ARMv8.2-A extensions are not available,

  -fexcess-precision=standard -> FLT_EVAL_METHOD = 0
  -fexcess-precision=fast -> FLT_EVAL_METHOD = 0

In c-family/c-cppbuiltin.c I've updated cpp_iec_559_value such that it
also allows setting __GEC_IEC_559 if FLT_EVAL_METHOD = 16, and I've updated
c_cpp_builtins to continue to set excess_precision = false if
FLT_EVAL_METHOD == 16. Then I've updated init_excess_precision in toplev.c
with logic to understand that for targets that provide _Float16, we can't
set flag_excess_precision to "fast" when FLT_EVAL_METHOD=0. This is because
FLT_EVAL_METHOD=0 requires predictably using the precision of float for
_Float16 types.
 
In tree.c, I've modified excess_precision_type with the logic discussed
above, promoting _Float16 to float (or wider) if we are required to.

The code needs some cleanup, and I need to decide what to do about the
issue Szabolcs brought up, but I'm hoping to be able to send patches in
the near future for GCC and soft-fp in glibc/libgcc.

Thanks,
James


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