Message ID | 20150522212414.GA25650@ibm-tiger.the-meissners.org |
---|---|
State | New |
Headers | show |
On Fri, May 22, 2015 at 5:24 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote: > This patch is the first in a series of patches that will eventually add support > for IEEE 128-bit floating point support to the PowerPC GCC compiler. At the > current time, we do not plan to change the default for long double. I added a > new type keyword (__float128) to get access to IEEE 128-bit floating point, and > another (__ibm128) to get access to IBM extended double type. > > Until all of the GCC and LIBGCC patches have been committed, you will not be > able to use IEEE 128-bit floating point, and -mfloat128-software will not be > turned on by default. > > This patch adds the new modes (KFmode and IFmode) and the switches > (-mfloat128-{none,software}). > > Due to the fact that TFmode in the PowerPC compiler either represents IEEE > 128-bit floating point or the IBM extended double (double-double) format. For > most PowerPC users, the default is to use IBM extended double for long double. > Because TFmode can be either floating point format, I added new new modes: > > KFmode -- IEEE 128-bit floating point > IFmode -- IBM extended double floating point > > If the default for TFmode is ibm extended double, the port will eventually use > KFmode for IEEE 128-bit floating point. Likewise if the default for TFmode is > IEEE 128-bit floating point, the port will use TFmode for IEEE 128-bit floating > point, and IFmode for IBM extended double. > > I have bootstraped these patches on a power7 and compared them to the unpatched > compiler. There were no changes when running make check. Are these patches ok > to install in the trunk? Mike, What is the purpose of the TARGET_LONG_DOUBLE_128 change in rs6000_hard_regno_mode_ok()? + /* If we don't allow 128-bit binary floating point, disallow the 128-bit + types from going in any registers. Similarly if __float128 is not + supported, don't allow __float128/__ibm128 types. */ + if (!TARGET_LONG_DOUBLE_128 + && (mode == TFmode || mode == KFmode || mode == IFmode)) + return false; Why is this necessary now? Thanks, David
Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over floating-point modes including these modes when they shouldn't, as discussed previously? If so, how do you deal (in subsequent patches?) with iterations that *should* include these modes? In particular, where libgcc uses __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an interation in c-cppbuiltin.c, how do you handle getting the relevant information in libgcc to build applicable libgcc functions for these modes? (I'm presuming that you do want complex arithmetic to work for both 128-bit types, for example, although you won't want them to be used for intermediate conversions in libgcc operations on other types.)
On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote: > Mike, > > What is the purpose of the TARGET_LONG_DOUBLE_128 change in > rs6000_hard_regno_mode_ok()? > > + /* If we don't allow 128-bit binary floating point, disallow the 128-bit > + types from going in any registers. Similarly if __float128 is not > + supported, don't allow __float128/__ibm128 types. */ > + if (!TARGET_LONG_DOUBLE_128 > + && (mode == TFmode || mode == KFmode || mode == IFmode)) > + return false; > > Why is this necessary now? I was trying to avoid problems if there was no move/convert patterns for KFmode/IFmode. I made it when I transitioned from SPECIAL_FLOAT_MODE to FRACTIONAL_FLOAT_MODE. Given there are 2 fractional float modes now, if the compiler was automatically trying to find a larger type than DFmode, it would first try IFmode, then KFmode, and finally TFmode (under the old SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of things). With the current set of patches, there is no move or convert options for IFmode/KFmode, but also the emulator functions are not properly defined. I can remove the lines and do the build again, if you would prefer. I don't think it is strictly necessary.
On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > floating-point modes including these modes when they shouldn't, as > discussed previously? > > If so, how do you deal (in subsequent patches?) with iterations that > *should* include these modes? In particular, where libgcc uses > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > interation in c-cppbuiltin.c, how do you handle getting the relevant > information in libgcc to build applicable libgcc functions for these > modes? (I'm presuming that you do want complex arithmetic to work for > both 128-bit types, for example, although you won't want them to be used > for intermediate conversions in libgcc operations on other types.) I have a catch-22 situation. We can't really do the glibc stuff until we have the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies the various TF files and modifies it for KF files. After we get the basic support in, we can then start tackling glibc. It may be when we get to doing the work in glibc itself, we will need to make further modifications. However, in order for the glibc people to start, I need the basic support in the compiler in the tree.
On Tue, Jun 2, 2015 at 2:27 PM, Michael Meissner <meissner@linux.vnet.ibm.com> wrote: > On Tue, Jun 02, 2015 at 01:43:08PM -0400, David Edelsohn wrote: >> Mike, >> >> What is the purpose of the TARGET_LONG_DOUBLE_128 change in >> rs6000_hard_regno_mode_ok()? >> >> + /* If we don't allow 128-bit binary floating point, disallow the 128-bit >> + types from going in any registers. Similarly if __float128 is not >> + supported, don't allow __float128/__ibm128 types. */ >> + if (!TARGET_LONG_DOUBLE_128 >> + && (mode == TFmode || mode == KFmode || mode == IFmode)) >> + return false; >> >> Why is this necessary now? > > I was trying to avoid problems if there was no move/convert patterns for > KFmode/IFmode. I made it when I transitioned from SPECIAL_FLOAT_MODE to > FRACTIONAL_FLOAT_MODE. Given there are 2 fractional float modes now, if the > compiler was automatically trying to find a larger type than DFmode, it would > first try IFmode, then KFmode, and finally TFmode (under the old > SPECIAL_FLOAT_MODE, it wouldn't look at those types in the normal course of > things). > > With the current set of patches, there is no move or convert options for > IFmode/KFmode, but also the emulator functions are not properly defined. The first patch is okay. This clearly is going to require a lot of interations with libgcc and GLIBC. Thanks, David
On Tue, 2 Jun 2015, Michael Meissner wrote: > On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > > floating-point modes including these modes when they shouldn't, as > > discussed previously? > > > > If so, how do you deal (in subsequent patches?) with iterations that > > *should* include these modes? In particular, where libgcc uses > > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > > interation in c-cppbuiltin.c, how do you handle getting the relevant > > information in libgcc to build applicable libgcc functions for these > > modes? (I'm presuming that you do want complex arithmetic to work for > > both 128-bit types, for example, although you won't want them to be used > > for intermediate conversions in libgcc operations on other types.) > > I have a catch-22 situation. We can't really do the glibc stuff until we have > the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies > the various TF files and modifies it for KF files. The functions I'm mainly thinking of are the libgcc2.c ones rather than the soft-fp ones (powi?f2 mul?c3 div?c3). > After we get the basic support in, we can then start tackling glibc. It may be > when we get to doing the work in glibc itself, we will need to make further > modifications. However, in order for the glibc people to start, I need the > basic support in the compiler in the tree. It's not obvious what glibc support should look like in the absence of a change to the default for long double; that would require discussion on libc-alpha at an early stage to establish a consensus on the design. libquadmath support should be easy (given working compiler / libgcc support). But if you want more than libquadmath support, there are several possible forms for support in glibc proper depending on e.g. whether you want to support a -m option to change long double, or using the functions via the __float128 type name and separate names for the functions, or both.
On Tue, Jun 2, 2015 at 4:14 PM, Joseph Myers <joseph@codesourcery.com> wrote: > On Tue, 2 Jun 2015, Michael Meissner wrote: > >> On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: >> > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over >> > floating-point modes including these modes when they shouldn't, as >> > discussed previously? >> > >> > If so, how do you deal (in subsequent patches?) with iterations that >> > *should* include these modes? In particular, where libgcc uses >> > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an >> > interation in c-cppbuiltin.c, how do you handle getting the relevant >> > information in libgcc to build applicable libgcc functions for these >> > modes? (I'm presuming that you do want complex arithmetic to work for >> > both 128-bit types, for example, although you won't want them to be used >> > for intermediate conversions in libgcc operations on other types.) >> >> I have a catch-22 situation. We can't really do the glibc stuff until we have >> the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies >> the various TF files and modifies it for KF files. > > The functions I'm mainly thinking of are the libgcc2.c ones rather than > the soft-fp ones (powi?f2 mul?c3 div?c3). > >> After we get the basic support in, we can then start tackling glibc. It may be >> when we get to doing the work in glibc itself, we will need to make further >> modifications. However, in order for the glibc people to start, I need the >> basic support in the compiler in the tree. > > It's not obvious what glibc support should look like in the absence of a > change to the default for long double; that would require discussion on > libc-alpha at an early stage to establish a consensus on the design. > > libquadmath support should be easy (given working compiler / libgcc > support). But if you want more than libquadmath support, there are > several possible forms for support in glibc proper depending on e.g. > whether you want to support a -m option to change long double, or using > the functions via the __float128 type name and separate names for the > functions, or both. Sounds like a fun night at a Czech pub during GNU Cauldron. - David
On Tue, Jun 02, 2015 at 08:14:12PM +0000, Joseph Myers wrote: > On Tue, 2 Jun 2015, Michael Meissner wrote: > > > On Tue, Jun 02, 2015 at 05:55:10PM +0000, Joseph Myers wrote: > > > Is the use of FRACTIONAL_FLOAT_MODE to avoid iterations over > > > floating-point modes including these modes when they shouldn't, as > > > discussed previously? > > > > > > If so, how do you deal (in subsequent patches?) with iterations that > > > *should* include these modes? In particular, where libgcc uses > > > __LIBGCC_<mode>_* macros predefined with -fbuilding-libgcc in an > > > interation in c-cppbuiltin.c, how do you handle getting the relevant > > > information in libgcc to build applicable libgcc functions for these > > > modes? (I'm presuming that you do want complex arithmetic to work for > > > both 128-bit types, for example, although you won't want them to be used > > > for intermediate conversions in libgcc operations on other types.) > > > > I have a catch-22 situation. We can't really do the glibc stuff until we have > > the compiler. Right now, I use a makefile on libgcc/config/rs6000 that copies > > the various TF files and modifies it for KF files. > > The functions I'm mainly thinking of are the libgcc2.c ones rather than > the soft-fp ones (powi?f2 mul?c3 div?c3). Ok, I will look into those. > > After we get the basic support in, we can then start tackling glibc. It may be > > when we get to doing the work in glibc itself, we will need to make further > > modifications. However, in order for the glibc people to start, I need the > > basic support in the compiler in the tree. > > It's not obvious what glibc support should look like in the absence of a > change to the default for long double; that would require discussion on > libc-alpha at an early stage to establish a consensus on the design. > > libquadmath support should be easy (given working compiler / libgcc > support). But if you want more than libquadmath support, there are > several possible forms for support in glibc proper depending on e.g. > whether you want to support a -m option to change long double, or using > the functions via the __float128 type name and separate names for the > functions, or both. There already is an option to change long double, but it currently does not work (and in fact is disabled in 64-bit environments). I see there are many roadblocks to changing the type of long double (i.e. making sure printf %Lg works correctly, etc.). None of the distros want another multilib (where long double is IEEE 128-bit). For the scope of GCC 6.0, my assumption is long double will remain IBM extended double. My assumption of the steps are: 1) Get the basic compiler support in. 2) Add the basic soft-float, either with my current hack or preferrably doing it right in glibc (I suspect we may want to temporarily do it via the hack, and when the glibc support is in, remove the hack). 3) Deal with all of the complexities of libgcc2 and glibc for the additional type. 4) Add float128 versions of the basic math libraries. For this it will probably be simpler if we can force long double to be IEEE 128-bit so you don't have to change as much code, but you want to suppress whatever check there will be to prevent user code from linking against the wrong library. 5) Add support in other libraries as needed (IBM's MASS library, the new vector library, libquadmath, etc.). Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there they have new names for IEEE 128-bit, etc.
On Tue, 2 Jun 2015, Michael Meissner wrote: > 4) Add float128 versions of the basic math libraries. For this it will > probably be simpler if we can force long double to be IEEE 128-bit so you > don't have to change as much code, but you want to suppress whatever check > there will be to prevent user code from linking against the wrong library. I'd say it's simpler if you don't force long double to be IEEE 128-bit (because then one answer is simply libquadmath, which already exists, to provide versions of libm functions for __float128, while making long double IEEE 128-bit affects a huge number of printf variant functions; libquadmath is a few years out of date with respect to glibc, but updating it shouldn't be hard). Building libm twice with different options seems much nastier. > Note, by the time of GCC 7.0, the C17/C++-17 standards may be final, and there > they have new names for IEEE 128-bit, etc. Since there is no project for a new major revision of the C standard (no work ongoing, no NWIP, etc.) I'm skeptical of any reference to "C17". And the last suggestion I saw referring to integration of the IEEE 754-2008 bindings into the C standard only suggested putting parts 1 and 2 in there (and even that involved some misconception about the extent to which those have been implemented). The relevant part for this is part 3, defining the _Float128 type name, functions such as sinf128, etc. Now, I think it would make sense eventually to support TS 18661 (any or all parts) in glibc, including providing the *f128 functions and so superseding libquadmath. That is, I think it would be appropriate to revisit the rejection of such support in <https://sourceware.org/ml/libc-alpha/2004-03/msg00326.html> and <https://sourceware.org/ml/libc-alpha/2004-05/msg00055.html> now appropriate standard bindings exist (but this is only my view, not a community consensus). But making the functions support building both for long double and for _Float128 would certainly be a large project. Support in accordance with TS 18661-3 would *not* involve any printf changes, since the TS 18661 approach is to use the strfrom* functions (new in part 1) for that purpose rather than e.g. adding new printf formats.
Index: gcc/config/rs6000/rs6000-modes.def =================================================================== --- gcc/config/rs6000/rs6000-modes.def (revision 223458) +++ gcc/config/rs6000/rs6000-modes.def (working copy) @@ -18,6 +18,13 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +/* IBM 128-bit floating point. IFmode and KFmode use the fractional float + support in order to declare 3 128-bit floating point types. */ +FRACTIONAL_FLOAT_MODE (IF, 106, 16, ibm_extended_format); + +/* Explicit IEEE 128-bit floating point. */ +FRACTIONAL_FLOAT_MODE (KF, 113, 16, ieee_quad_format); + /* 128-bit floating point. ABI_V4 uses IEEE quad, AIX/Darwin adjust this in rs6000_option_override_internal. */ FLOAT_MODE (TF, 16, ieee_quad_format); Index: gcc/config/rs6000/rs6000.opt =================================================================== --- gcc/config/rs6000/rs6000.opt (revision 223458) +++ gcc/config/rs6000/rs6000.opt (working copy) @@ -600,3 +600,19 @@ Allow float/double variables in upper re moptimize-swaps Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save Analyze and remove doubleword swaps from VSX computations. + +mfloat128- +Target RejectNegative Joined Enum(float128_type_t) Var(TARGET_FLOAT128) Init(FLOAT128_UNSET) Save +-mfloat128-{software,none} - Specify how IEEE 128-bit floating point is used. + +Enum +Name(float128_type_t) Type(enum float128_type_t) + +EnumValue +Enum(float128_type_t) String(none) Value(FLOAT128_NONE) + +EnumValue +Enum(float128_type_t) String(software) Value(FLOAT128_SW) + +EnumValue +Enum(float128_type_t) String(sw) Value(FLOAT128_SW) Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 223458) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -1817,6 +1817,16 @@ rs6000_hard_regno_mode_ok (int regno, ma && IN_RANGE (last_regno, FIRST_GPR_REGNO, LAST_GPR_REGNO) && ((regno & 1) == 0)); + /* If we don't allow 128-bit binary floating point, disallow the 128-bit + types from going in any registers. Similarly if __float128 is not + supported, don't allow __float128/__ibm128 types. */ + if (!TARGET_LONG_DOUBLE_128 + && (mode == TFmode || mode == KFmode || mode == IFmode)) + return false; + + if (!TARGET_FLOAT128 && (mode == KFmode || mode == IFmode)) + return false; + /* VSX registers that overlap the FPR registers are larger than for non-VSX implementations. Don't allow an item to be split between a FP register and an Altivec register. Allow TImode in all VSX registers if the user @@ -2086,6 +2096,7 @@ rs6000_debug_reg_global (void) const char *trace_str; const char *abi_str; const char *cmodel_str; + const char *float128_str; struct cl_target_option cl_opts; /* Modes we want tieable information on. */ @@ -2099,6 +2110,8 @@ rs6000_debug_reg_global (void) SFmode, DFmode, TFmode, + IFmode, + KFmode, SDmode, DDmode, TDmode, @@ -2445,6 +2458,15 @@ rs6000_debug_reg_global (void) fprintf (stderr, DEBUG_FMT_S, "e500_double", (TARGET_E500_DOUBLE ? "true" : "false")); + switch (TARGET_FLOAT128) + { + case FLOAT128_NONE: float128_str = "none"; break; + case FLOAT128_SW: float128_str = "software"; break; + default: float128_str = "unknown"; break; + } + + fprintf (stderr, DEBUG_FMT_S, "float128", float128_str); + if (TARGET_LINK_STACK) fprintf (stderr, DEBUG_FMT_S, "link_stack", "true"); @@ -3703,6 +3725,13 @@ rs6000_option_override_internal (bool gl && optimize >= 3) rs6000_isa_flags |= OPTION_MASK_P8_FUSION_SIGN; + /* Set the appropriate IEEE 128-bit floating option. Do not enable float128 + support by default until the libgcc support is added. */ + if (TARGET_FLOAT128 == FLOAT128_UNSET) + TARGET_FLOAT128 = FLOAT128_NONE; + else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX) + error ("-mfloat128-software requires VSX support"); + if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags); @@ -14320,6 +14349,8 @@ rs6000_init_builtins (void) tree tdecl; tree ftype; machine_mode mode; + machine_mode ieee128_mode; + machine_mode ibm128_mode; if (TARGET_DEBUG_BUILTIN) fprintf (stderr, "rs6000_init_builtins%s%s%s%s\n", @@ -14387,6 +14418,32 @@ rs6000_init_builtins (void) dfloat128_type_internal_node = dfloat128_type_node; void_type_internal_node = void_type_node; + /* 128-bit floating point support. KFmode is IEEE 128-bit floating point. + IFmode is the IBM extended 128-bit format that is a pair of doubles. + TFmode will be either IEEE 128-bit floating point or the IBM double-double + format that uses a pair of doubles, depending on the switches and + defaults. */ + if (TARGET_IEEEQUAD) + { + ieee128_mode = TFmode; + ibm128_mode = IFmode; + } + else + { + ieee128_mode = KFmode; + ibm128_mode = TFmode; + } + + ieee128_float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ieee128_float_type_node) = 128; + layout_type (ieee128_float_type_node); + SET_TYPE_MODE (ieee128_float_type_node, ieee128_mode); + + ibm128_float_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (ibm128_float_type_node) = 128; + layout_type (ibm128_float_type_node); + SET_TYPE_MODE (ibm128_float_type_node, ibm128_mode); + /* Initialize the modes for builtin_function_type, mapping a machine mode to tree type node. */ builtin_mode_to_type[QImode][0] = integer_type_node; @@ -14399,6 +14456,8 @@ rs6000_init_builtins (void) builtin_mode_to_type[TImode][1] = unsigned_intTI_type_node; builtin_mode_to_type[SFmode][0] = float_type_node; builtin_mode_to_type[DFmode][0] = double_type_node; + builtin_mode_to_type[IFmode][0] = ibm128_float_type_node; + builtin_mode_to_type[KFmode][0] = ieee128_float_type_node; builtin_mode_to_type[TFmode][0] = long_double_type_node; builtin_mode_to_type[DDmode][0] = dfloat64_type_node; builtin_mode_to_type[TDmode][0] = dfloat128_type_node; Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 223458) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -2715,6 +2715,8 @@ enum rs6000_builtin_type_index RS6000_BTI_dfloat64, /* dfloat64_type_node */ RS6000_BTI_dfloat128, /* dfloat128_type_node */ RS6000_BTI_void, /* void_type_node */ + RS6000_BTI_ieee128_float, /* ieee 128-bit floating point */ + RS6000_BTI_ibm128_float, /* IBM 128-bit floating point */ RS6000_BTI_MAX }; @@ -2769,6 +2771,8 @@ enum rs6000_builtin_type_index #define dfloat64_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat64]) #define dfloat128_type_internal_node (rs6000_builtin_types[RS6000_BTI_dfloat128]) #define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void]) +#define ieee128_float_type_node (rs6000_builtin_types[RS6000_BTI_ieee128_float]) +#define ibm128_float_type_node (rs6000_builtin_types[RS6000_BTI_ibm128_float]) extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX]; extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT]; Index: gcc/config/rs6000/rs6000-opts.h =================================================================== --- gcc/config/rs6000/rs6000-opts.h (revision 223458) +++ gcc/config/rs6000/rs6000-opts.h (working copy) @@ -79,6 +79,15 @@ enum fpu_type_t FPU_DF_FULL /* Full Double Single Precision FPU */ }; + +/* Float128 support. */ +enum float128_type_t +{ + FLOAT128_UNSET = -1, /* Initial value. */ + FLOAT128_NONE, /* No __float128 support. */ + FLOAT128_SW /* software __float128 support. */ +}; + /* Types of costly dependences. */ enum rs6000_dependence_cost {