Re: Implement C _FloatN, _FloatNx types [version 2]
> 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]
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]
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]
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