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

2016-06-22 Thread FX
> Fortran note: the float128_type_node used in the Fortran front end is
> renamed to gfc_float128_type_node, since the semantics are different:
> in particular, if long double has binary128 format, then the new
> language-independent float128_type_node is a distinct type that also
> has binary128 format, but the Fortran node is expected to be NULL in
> that case.  Likewise, Fortran's complex_float128_type_node is renamed
> to gfc_complex_float128_type_node.

Fortran part is OK.


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

2016-06-22 Thread Joseph Myers
Here is patch version 2, updated to apply without conflicts to current 
trunk (there was a conflict with r237714 moving cases over RID_* around) 
but with no other changes.  (In particular, with no further changes to the 
PowerPC choice of mode - in this patch it matches what __float128 already 
does, and if the PowerPC maintainers decide that (FLOAT128_IEEE_P 
(TFmode)) ? TFmode : KFmode as used for *q constants is preferable, that 
can easily be used instead.)

Can we get the non-C-front-end parts (which are actually pretty 
straightforward) reviewed so we can get on to adding appropriate built-in 
functions on top of this, and other followup changes?


ISO/IEC TS 18661-3:2015 defines C bindings to IEEE interchange and
extended types, in the form of _FloatN and _FloatNx type names with
corresponding fN/FN and fNx/FNx constant suffixes and FLTN_* / FLTNX_*
 macros.  This patch implements support for this feature in
GCC.

The _FloatN types, for N = 16, 32, 64 or >= 128 and a multiple of 32,
are types encoded according to the corresponding IEEE interchange
format (endianness unspecified; may use either the NaN conventions
recommended in IEEE 754-2008, or the MIPS NaN conventions, since the
choice of convention is only an IEEE recommendation, not a
requirement).  The _FloatNx types, for N = 32, 64 and 128, are IEEE
"extended" types: types extending a narrower format with range and
precision at least as big as those specified in IEEE 754 for each
extended type (and with unspecified representation, but still
following IEEE semantics for their values and operations - and with
the set of values being determined by the precision and the maximum
exponent, which means that while Intel "extended" is suitable for
_Float64x, m68k "extended" is not).  These types are always distinct
from and not compatible with each other and the standard floating
types float, double, long double; thus, double, _Float64 and _Float32x
may all have the same ABI, but they are three still distinct types.
The type names may be used with _Complex to construct corresponding
complex types (unlike __float128, which acts more like a typedef name
than a keyword - thus, this patch may be considered to fix PR
c/32187).  The new suffixes can be combined with GNU "i" and "j"
suffixes for constants of complex types (e.g. 1.0if128, 2.0f64i).

The set of types supported is implementation-defined.  In this GCC
patch, _Float32 is SFmode if that is suitable; _Float32x and _Float64
are DFmode if that is suitable; _Float128 is TFmode if that is
suitable; _Float64x is XFmode if that is suitable, and otherwise
TFmode if that is suitable.  There is a target hook to override the
choices if necessary.  "Suitable" means both conforming to the
requirements of that type, and supported as a scalar type including in
libgcc.  The ABI is whatever the back end does for scalars of that
mode (but note that _Float32 is passed without promotion in variable
arguments, unlike float).  All the existing issues with exceptions and
rounding modes for existing types apply equally to the new type names.

No GCC port supports a floating-point format suitable for _Float128x.
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.

GCC has some prior support for nonstandard floating-point types in the
form of __float80 and __float128.  Where these were previously types
distinct from long double, they are made by this patch into aliases
for _Float64x / _Float128 if those types have the required properties.

In principle the set of possible _FloatN types is infinite.  This
patch hardcodes the four such types for N <= 128, but with as much
code as possible using loops over types to minimize the number of
places with such hardcoding.  I don't think it's likely any further
such types will be of use in future (or indeed that formats suitable
for _Float128x will actually be implemented).  There is a corner case
that all _FloatN, for N >= 128 and a multiple of 32, should be treated
as keywords even when the corresponding type is not supported; I
intend to deal with that in a followup patch.

Tests are added for various functionality of the new types, mostly
using type-generic headers.  PowerPC maintainers should note that the
tests do not do anything regarding passing special options to 

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

2016-06-21 Thread Joseph Myers
On Tue, 21 Jun 2016, Michael Meissner wrote:

> While from one perspective, it would have been cleaner if the PowerPC
> had separate internal types for IBM extended double and IEEE 128-bit floating
> point.  But the way the compiler has been implemented is that TFmode is which
> ever type is the default.  Typically, in the Linux environment, this is IBM
> extended double, but we are hoping in the future to change the default to make
> long double IEEE 128-bit.  So, I think we need to do something like:
> 
> static machine_mode
> rs6000_floatn_mode (int n, bool extended)
> {
>   if (extended)
> {
>   switch (n)
>   {
>   case 32:
> return DFmode;
> 
>   case 64:
> if (TARGET_FLOAT128)
>   return (TARGET_IEEEQUAD) ? TFmode : KFmode;

That's essentially what I had in the first patch version.  I.e., you and 
Bill are making contradictory statements about whether always to use 
KFmode (in which case *q constants should be fixed to match) or whether to 
prefer TFmode when it's binary128 (in which case no fixes beyond my patch 
(with the first version of this function) are needed as my patch will make 
__float128 into an alias for _Float128, which will prefer TFmode when it's 
binary128).

> As an aside, one of the issues, I'm currently grappling with is how to enable
> the __float128 machinery without enabling the __float128 keyword (PR 70589).
> The reason is we need to create the various built-in functions for IEEE 
> 128-bit
> functions, which means creating the type and keyword support.

Perhaps it would be best not to allow __float128 to be disabled?  I.e. 
have it always available for 64-bit and never available for 32-bit (or 
something like that).  Or at least don't allow it to change during the 
source file.  Because we want these functions to end up in generic code 
rather than target-specific.  And at least the C-family built-ins 
machinery handles not creating a built-in function if its type would be 
error_mark_node, and using error_mark_node for types derived from 
error_mark_node.  That is, if in the generic code we have

DEF_PRIMITIVE_TYPE (BT_FLOAT128, float128_type_node ? float_128_type_node : 
error_mark_node)

in builtin-types.def, then it should be possible to list all the relevant 
functions in builtins.def and have them only created when the type is 
enabled.  But you'll run into problems if there are conditions for 
function availability changing part way through the source file  
(There's existing machinery for targets to change built-in function 
availability part way through the source file, but it seems likely to be 
nasty to apply that to target-independent functions.)

> Another thing that I'm grappling with is how to identify when the floating
> point emulation functions have been built.  Right now, it is only built for
> 64-bit Linux systems, and it is not built for AIX, BSD, or the various 32-bit
> embedded targets.

See the libgcc_floating_mode_supported_p hook.  (It doesn't do much, and 
you might need to implement it for your target, but it's the right idea.)

> However, I suspect that in the future, we may have users that want to do
> arithmetic in this format (particularly vectors).  This comes from people
> wanting to interface with attached GPUs that often times support HFmode, and
> with machine learning systems that does not need the precision.  So, we should
> at least think what is needed to enable HFmode as a real type.

Basically, you need to define an ABI, and you need changes to excess 
precision support which is currently geared to the x87 case.

> > GCC has some prior support for nonstandard floating-point types in the
> > form of __float80 and __float128.  Where these were previously types
> > distinct from long double, they are made by this patch into aliases
> > for _Float64x / _Float128 if those types have the required properties.
> 
> And of course other machine dependent non-standard floating point types 
> such as IBM extended double.

Which cannot be _FloatN / _FloatNx types; those names are strictly for 
types with IEEE semantics (and representation, in the _FloatN case).  
float, double and long double are much more flexible about possible 
formats than _FloatN and _FloatNx.

> In addition, there is the question of what to do on the embedded machines that
> might use IEEE format for floating point, but does not support all of the
> features in IEEE 754R such as NaNs, infinities, de-normal numbers, negative 0,
> etc.

Those also cannot be _FloatN / _FloatNx types.  Note how my real.c changes 
mark spu_single_format as not suitable for such a type.

-- 
Joseph S. Myers
jos...@codesourcery.com


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

2016-06-21 Thread Michael Meissner
On Tue, Jun 21, 2016 at 05:41:36PM +, Joseph Myers wrote:
> [Changes in version 2 of the patch:
> 
> * PowerPC always uses KFmode for _Float128 and _Float64x when those
>   types are supported, not TFmode.

While from one perspective, it would have been cleaner if the PowerPC
had separate internal types for IBM extended double and IEEE 128-bit floating
point.  But the way the compiler has been implemented is that TFmode is which
ever type is the default.  Typically, in the Linux environment, this is IBM
extended double, but we are hoping in the future to change the default to make
long double IEEE 128-bit.  So, I think we need to do something like:

static machine_mode
rs6000_floatn_mode (int n, bool extended)
{
  if (extended)
{
  switch (n)
{
case 32:
  return DFmode;

case 64:
  if (TARGET_FLOAT128)
return (TARGET_IEEEQUAD) ? TFmode : KFmode;
  else
return VOIDmode;

case 128:
  return VOIDmode;

default:
  /* Those are the only valid _FloatNx types.  */
  gcc_unreachable ();
}
}
  else
{
  switch (n)
{
case 32:
  return SFmode;

case 64:
  return DFmode;

case 128:
  if (TARGET_FLOAT128)
return (TARGET_IEEEQUAD) ? TFmode : KFmode;
  else
return VOIDmode;

default:
  return VOIDmode;
}
}
}

As an aside, one of the issues, I'm currently grappling with is how to enable
the __float128 machinery without enabling the __float128 keyword (PR 70589).
The reason is we need to create the various built-in functions for IEEE 128-bit
functions, which means creating the type and keyword support.

As Richard Biener and I discussed, the way I created the types using
FRACTIONAL_FLOAT_MODE for IFmode/KFmode isn't really ideal.
https://gcc.gnu.org/ml/gcc-patches/2016-06/msg01114.html

It would have made things simpler if there was a MD hook to control what
automatically widens to what.  I tried to implement it in the early days, but I
never came up with code that did what I wanted.  I use rs6000_invalid_binary_op
to do this to some extent.

Another thing that I'm grappling with is how to identify when the floating
point emulation functions have been built.  Right now, it is only built for
64-bit Linux systems, and it is not built for AIX, BSD, or the various 32-bit
embedded targets.

> No GCC port supports a floating-point format suitable for _Float128x.
> 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.

ISA 3.0 (Power9) does have instructions to convert to/from 16-bit floating
point to 32-bit floating point.  Right now, it is just conversion to/from
storage format to a more normal format (similar to _Decimal32 where there are
no instructions to operate on 32-bit decimal data).  At the moment, we don't
have support for these instructions, but we will likely do it in the future.

However, I suspect that in the future, we may have users that want to do
arithmetic in this format (particularly vectors).  This comes from people
wanting to interface with attached GPUs that often times support HFmode, and
with machine learning systems that does not need the precision.  So, we should
at least think what is needed to enable HFmode as a real type.

> GCC has some prior support for nonstandard floating-point types in the
> form of __float80 and __float128.  Where these were previously types
> distinct from long double, they are made by this patch into aliases
> for _Float64x / _Float128 if those types have the required properties.

And of course other machine dependent non-standard floating point types such as
IBM extended double.

In addition, there is the question of what to do on the embedded machines that
might use IEEE format for floating point, but does not support all of the
features in IEEE 754R such as NaNs, infinities, de-normal numbers, negative 0,
etc.

As I said in my previous message, what ever we do in this space needs to be
backwards compatible with existing usage in GCC 6.x.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797