Message ID | 20180104230555.GA4847@ibm-tiger.the-meissners.org |
---|---|
State | New |
Headers | show |
Series | , Add optional IEEE/IBM long double multilib support | expand |
On Thu, 4 Jan 2018, Michael Meissner wrote: > (CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to > accomidate -mabi=ieeelongdouble multilibs. Why is that correct in the -mabi=ibmlongdouble case? As I understand it, TFtype is always of mode TFmode (it would certainly be confusing if it sometimes had a different mode), but TFmode's format depends on the selected ABI. Where this code uses __float128, it requires something that is always of IEEE binary128 format. In the -mabi=ieeelongdouble case, that's indeed TFtype, but not in the -mabi=ibmlongdouble case when TFmode has ibm128 format. In C code, _Float128 and _Complex _Float128 should always be available when the binary128 format is supported, so I think the code needing that format can safely use those. > (__mulkc3): Use TFmode/TCmode for float128 scalar/complex types. > (__divkc3): Use TFmode/TCmode for float128 scalar/complex types. > * config/rs6000/extendkftf2-sw.c (__extendkftf2_sw): Likewise. > * config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise. And likewise here. (My understanding is that each of the libgcc functions is meant to have a particular ABI that does not depend on the format of long double - so the "tf" and "tc" functions refer to ibm128 format, unconditionally, and the "kf" and "kc" ones to binary128 format, unconditionally. I have not checked whether the libfuncs handling in init_float128_ibm and init_float128_ieee is sufficient to achieve this in all cases. In particular, does complex arithmetic always use the correct one of "kc" and "tc" depending on the long double format? What about __builtin_powil - does that properly use __powitf2 and __powikf2 as appropriate, or do you have the ABI of __powitf2 depending on the multilib?)
On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > This patch is the beginning step to switching the PowerPC long double support > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > will be necessary to have this patch or a similar patch to allow the GLIBC team > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > out, we can decide to switch the default. It is likely, the default will only > be switched on the 64-bit little endian PowerPC systems, when a distribution > goes through a major level, such that they can contemplate major changes. When you're mentioning multilibs, does that mean that we'll have two ABI incompatible libgcc.so.* libraries, two ABI incompatible libstdc++.so.* libraries etc.? Just one or 2 libc.so.*/libm.so.*? At least when doing the long double format double to doubledouble transition (or on other targets to quad) last time we've managed to make it ABI compatible. Jakub
On Fri, 5 Jan 2018, Jakub Jelinek wrote: > On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > > This patch is the beginning step to switching the PowerPC long double support > > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > > will be necessary to have this patch or a similar patch to allow the GLIBC team > > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > > out, we can decide to switch the default. It is likely, the default will only > > be switched on the 64-bit little endian PowerPC systems, when a distribution > > goes through a major level, such that they can contemplate major changes. > > When you're mentioning multilibs, does that mean that we'll have two ABI > incompatible libgcc.so.* libraries, two ABI incompatible libstdc++.so.* > libraries etc.? Just one or 2 libc.so.*/libm.so.*? The existing GCC code tries to fix the libgcc function names so *tf* always means IBM long double and *kf* always means IEEE long double. As noted in my reply to this patch, I suspect it might fail to handle __div?c3, __mul?c3 and __powi?c2 (at least) properly to avoid two different libgcc ABIs there. I don't know the intent for libstdc++, libgfortran etc. - but it's been stated the intent is a single set of glibc libraries. (Of course a distribution probably has other libraries influenced by the long double format in some way.)
On Fri, Jan 05, 2018 at 05:28:03PM +0000, Joseph Myers wrote: > On Thu, 4 Jan 2018, Michael Meissner wrote: > > > (CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to > > accomidate -mabi=ieeelongdouble multilibs. > > Why is that correct in the -mabi=ibmlongdouble case? The PowerPC TFmode has always been 'special'. It would mirror the 128-bit long double format. For the one port that actually used IEEE 128-bit floating point, TFmode was IEEE. For the the majority of ports TFmode is IBM extended double. So when I began this journey to add IEEE 128-bit support, I had to fit it into this framework. If long double is IBM extended double: TFmode is IBM extended double scalar TCmode is IBM extended double complex KFmode is IEEE scalar KCmode is IEEE complex IFmode is not used ICmode is not used If long double is IEEE 128-bit (i.e. -mabi=ieeelongdouble): TFmode is IEEE scalar TCmode is IEEE complex KFmode is not used KCmode is not used IFmode is IBM extended double scalar ICmode is IBM extended double complex We are just starting to look at the implications of switching the long double type from IBM extended to IEEE. While I would hope that eventualy GLIBC can do something with versioning so that we avoid having to do multilibs, I suspect during initial development, we will need multilibs just to get things right. Then perhaps GLIBC can do something like the original support for -mlong-double-64 and -mlong-double-128 went in. However, since I don't work on GLIBC, I don't know how hard it is. I figured we would need multilibs as a crutch during initial development. > As I understand it, TFtype is always of mode TFmode (it would certainly be > confusing if it sometimes had a different mode), but TFmode's format > depends on the selected ABI. Where this code uses __float128, it requires > something that is always of IEEE binary128 format. In the > -mabi=ieeelongdouble case, that's indeed TFtype, but not in the > -mabi=ibmlongdouble case when TFmode has ibm128 format. > > In C code, _Float128 and _Complex _Float128 should always be available > when the binary128 format is supported, so I think the code needing that > format can safely use those. Yes, in C code _Float128 _Comples works. The trouble is compiling libstdc++-v3. In C++, we don't have _Float128, and __float128 _Complex does not work for either x86 or PowerPC. So on PowerPC the code from bits/floatn.h is: /* Defined to a complex binary128 type if __HAVE_FLOAT128 is 1. */ #if __HAVE_FLOAT128 # if !__GNUC_PREREQ (7, 0) || defined __cplusplus /* Add a typedef for older GCC compilers which don't natively support _Complex _Float128. */ typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__KC__))); # define __CFLOAT128 __cfloat128 # else # define __CFLOAT128 _Complex _Float128 # endif #endif Obviously, in a future release of GLIBC (via AT 11.0-3) we will fix that, but it made the job of doing the initial port eaiser. The problem is we need to get stuff into GCC so that GLIBC can start to add the appropriate changes. > > (__mulkc3): Use TFmode/TCmode for float128 scalar/complex types. > > (__divkc3): Use TFmode/TCmode for float128 scalar/complex types. > > * config/rs6000/extendkftf2-sw.c (__extendkftf2_sw): Likewise. > > * config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise. > > And likewise here. > > (My understanding is that each of the libgcc functions is meant to have a > particular ABI that does not depend on the format of long double - so the > "tf" and "tc" functions refer to ibm128 format, unconditionally, and the > "kf" and "kc" ones to binary128 format, unconditionally. I have not > checked whether the libfuncs handling in init_float128_ibm and > init_float128_ieee is sufficient to achieve this in all cases. In > particular, does complex arithmetic always use the correct one of "kc" and > "tc" depending on the long double format? What about __builtin_powil - > does that properly use __powitf2 and __powikf2 as appropriate, or do you > have the ABI of __powitf2 depending on the multilib?) Libgcc does not need to be multilibed. It uses separate functions. What does currently need to be multilibed is libstdc++-v3 and possibly GLIBC.
On Fri, Jan 05, 2018 at 06:33:50PM +0100, Jakub Jelinek wrote: > On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > > This patch is the beginning step to switching the PowerPC long double support > > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > > will be necessary to have this patch or a similar patch to allow the GLIBC team > > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > > out, we can decide to switch the default. It is likely, the default will only > > be switched on the 64-bit little endian PowerPC systems, when a distribution > > goes through a major level, such that they can contemplate major changes. > > When you're mentioning multilibs, does that mean that we'll have two ABI > incompatible libgcc.so.* libraries, two ABI incompatible libstdc++.so.* > libraries etc.? Just one or 2 libc.so.*/libm.so.*? > > At least when doing the long double format double to doubledouble transition > (or on other targets to quad) last time we've managed to make it ABI > compatible. We are hoping that it eventually will not need multilibs. But during the initial development, it is likely that we will need to use multilibs. That is what the patch is for -- to allow building the compiler that supports multilibs, but it is not on by default. Part of the issue is GCC and GLIBC rev on different cycles and are done by different people. I have to guess what GLIBC will need, so that we have the GLIBC solution by the time GCC 9 is ready.
On Fri, Jan 05, 2018 at 05:47:39PM +0000, Joseph Myers wrote: > On Fri, 5 Jan 2018, Jakub Jelinek wrote: > > > On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > > > This patch is the beginning step to switching the PowerPC long double support > > > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > > > will be necessary to have this patch or a similar patch to allow the GLIBC team > > > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > > > out, we can decide to switch the default. It is likely, the default will only > > > be switched on the 64-bit little endian PowerPC systems, when a distribution > > > goes through a major level, such that they can contemplate major changes. > > > > When you're mentioning multilibs, does that mean that we'll have two ABI > > incompatible libgcc.so.* libraries, two ABI incompatible libstdc++.so.* > > libraries etc.? Just one or 2 libc.so.*/libm.so.*? > > The existing GCC code tries to fix the libgcc function names so *tf* > always means IBM long double and *kf* always means IEEE long double. As > noted in my reply to this patch, I suspect it might fail to handle > __div?c3, __mul?c3 and __powi?c2 (at least) properly to avoid two > different libgcc ABIs there. > > I don't know the intent for libstdc++, libgfortran etc. - but it's been > stated the intent is a single set of glibc libraries. (Of course a > distribution probably has other libraries influenced by the long double > format in some way.) It would have been much simpler if we didn't already have a 128-bit floating point type. But we had the existing long double support. In any case, even if you switch default long double format to IEEE, the kf/kc functions in libgcc will be called, even though the type is now TFmode/TCmode. It is unfortunate that the IBM extended double support did not define all of the interfaces to be __gcc_q<xxx>, but there were some tf/tc functions defined that are called, and I needed to pick unique names.
On Fri, Jan 05, 2018 at 02:07:51PM -0500, Michael Meissner wrote: > Yes, in C code _Float128 _Comples works. The trouble is compiling > libstdc++-v3. In C++, we don't have _Float128, and __float128 _Complex does > not work for either x86 or PowerPC. So on PowerPC the code from bits/floatn.h > is: Well, libstdc++-v3 should be certainly easier than glibc, at least assuming that ICmode mangles differently from KCmode, because it should be just a matter of compiling the subset of symbols refering to long double twice. Jakub
On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > This patch is the beginning step to switching the PowerPC long double support > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > will be necessary to have this patch or a similar patch to allow the GLIBC team > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > out, we can decide to switch the default. It is likely, the default will only > be switched on the 64-bit little endian PowerPC systems, when a distribution > goes through a major level, such that they can contemplate major changes. In doing some testing on a big endian system, it getting hairy to add support to add optional multilibs for ieee/ibm. On the BE system, the default cpu is a power4, and so the IEEE emulator is not built unless you configure to make power7, power8, or power9 the default cpu. In addition, the BE system already has multilibs for 64 vs. 32 bit. While these things can be handled, it is not currently planned to ultimately switch the long double format in BE. So, this patch replaces the previous patch, and it only allows you to switch the long double format for powerpc64le-*-linux* systems. Except for configure.ac and configure, all of the other changes are the same. I have tested the patch on BE systems, and it builds normally providing you do not use the --with-long-double-format option. [gcc] 2018-01-05 Michael Meissner <meissner@linux.vnet.ibm.com> * configure.ac (--with-long-double-format): Add support for configuration option to change the default long double format on little endian PowerPC Linux systems. * configure: Regenerate. * config.gcc (powerpc*-linux*-*): Add support for --with-long-double-format={ieee,ibm}. If the format is explicit set, also set up IBM and IEEE multilibs. * config/rs6000/rs6000.h (FLOAT128_IEEE_P): Explicitly check for 128-bit long doubles before checking TFmode or TCmode. (FLOAT128_IBM_P): Likewise. (TARGET_IEEEQUAD_MULTILIB): Set to 0 if not already defined. * config/rs6000/rs6000.c (rs6000_option_override_internal): If we have IBM/IEEE multilibs, don't give a warning if the user chagnes the long double format. (is_complex_IBM_long_double): Explicitly check for 128-bit long doubles before checking TCmode. * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): If long double is IEEE, define __KC__ and __KF__ to allow floatn.h to be used without modification. * config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Specify the -mabi={ieee,ibm}longdouble default for multilibs. (MULTILIB_DEFAULTS): Likewise. * config/rs6000/t-ldouble: New file, add IEEE/IBM long double multilibs. [libgcc] 2018-01-05 Michael Meissner <meissner@linux.vnet.ibm.com> * config/rs6000/quad-float128.h (IBM128_TYPE): Explicitly use __ibm128, instead of trying to use long double. (CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to accomidate -mabi=ieeelongdouble multilibs. (CVT_IBM128_TO_FLOAT128): Likewise. * config/rs6000/ibm-ldouble.c (IBM128_TYPE): New macro to define the appropriate IBM extended double type. (__gcc_qadd): Change all occurances of long double to IBM128_TYPE. (__gcc_qsub): Likewise. (__gcc_qmul): Likewise. (__gcc_qdiv): Likewise. (pack_ldouble): Likewise. (__gcc_qneg): Likewise. (__gcc_qeq): Likewise. (__gcc_qne): Likewise. (__gcc_qge): Likewise. (__gcc_qle): Likewise. (__gcc_stoq): Likewise. (__gcc_dtoq): Likewise. (__gcc_itoq): Likewise. (__gcc_utoq): Likewise. (__gcc_qunord): Likewise. * config/rs6000/_mulkc3.c (toplevel): Include soft-fp.h and quad-float128.h for the definitions. (COPYSIGN): Use the f128 version instead of the q version. (INFINITY): Likewise. (__mulkc3): Use TFmode/TCmode for float128 scalar/complex types. * config/rs6000/_divkc3.c (toplevel): Include soft-fp.h and quad-float128.h for the definitions. (COPYSIGN): Use the f128 version instead of the q version. (INFINITY): Likewise. (FABS): Likewise. (__divkc3): Use TFmode/TCmode for float128 scalar/complex types. * config/rs6000/extendkftf2-sw.c (__extendkftf2_sw): Likewise. * config/rs6000/trunctfkf2-sw.c (__trunctfkf2_sw): Likewise.
On Fri, Jan 05, 2018 at 08:22:57PM +0100, Jakub Jelinek wrote: > On Fri, Jan 05, 2018 at 02:07:51PM -0500, Michael Meissner wrote: > > Yes, in C code _Float128 _Comples works. The trouble is compiling > > libstdc++-v3. In C++, we don't have _Float128, and __float128 _Complex does > > not work for either x86 or PowerPC. So on PowerPC the code from bits/floatn.h > > is: > > Well, libstdc++-v3 should be certainly easier than glibc, at least assuming > that ICmode mangles differently from KCmode, because it should be just a > matter of compiling the subset of symbols refering to long double twice. Yep. But as I said, I think we will need the crutch of having multilibs initially.
On Fri, 5 Jan 2018, Michael Meissner wrote: > On Fri, Jan 05, 2018 at 05:28:03PM +0000, Joseph Myers wrote: > > On Thu, 4 Jan 2018, Michael Meissner wrote: > > > > > (CVT_FLOAT128_TO_IBM128): Use TFtype instead of __float128 to > > > accomidate -mabi=ieeelongdouble multilibs. > > > > Why is that correct in the -mabi=ibmlongdouble case? > > The PowerPC TFmode has always been 'special'. It would mirror the 128-bit long > double format. For the one port that actually used IEEE 128-bit floating > point, TFmode was IEEE. For the the majority of ports TFmode is IBM extended > double. I don't think this answers my question. CVT_FLOAT128_TO_IBM128 has an argument VALUE that is always of IEEE format. You're doing "TFtype __value = (VALUE);". In the case where TFmode is IBM long double, and so therefore is TFtype, this will do an unwanted conversion. I'd expect it to result in __extendkftf2 recursively calling itself, in fact. If it does not, what's wrong with my reasoning, and what exactly does that line do in the case where long double is ibm128? > Yes, in C code _Float128 _Comples works. The trouble is compiling > libstdc++-v3. In C++, we don't have _Float128, and __float128 _Complex does My comments are about changes to code in libgcc, not about libstdc++-v3. > > (My understanding is that each of the libgcc functions is meant to have a > > particular ABI that does not depend on the format of long double - so the > > "tf" and "tc" functions refer to ibm128 format, unconditionally, and the > > "kf" and "kc" ones to binary128 format, unconditionally. I have not > > checked whether the libfuncs handling in init_float128_ibm and > > init_float128_ieee is sufficient to achieve this in all cases. In > > particular, does complex arithmetic always use the correct one of "kc" and > > "tc" depending on the long double format? What about __builtin_powil - > > does that properly use __powitf2 and __powikf2 as appropriate, or do you > > have the ABI of __powitf2 depending on the multilib?) > > Libgcc does not need to be multilibed. It uses separate functions. What does > currently need to be multilibed is libstdc++-v3 and possibly GLIBC. I don't see how you ensure __mulkc3, for example, always uses IEEE format, given that you're making it use TFtype (= IBM long double in the default case). I don't see how you ensure that, when IEEE long double is the default, __multc3 is still built to use IBM long double, which is the ABI for that function name. Likewise for __divkc3, __divtc3, __powitf2, __powikf2. For that matter, when building with IEEE long double as the default, how do you ensure that libgcc functions such as __fixtfti (built from generic libgcc2.c sources, in that case) are built with the proper ABI, meaning use of IFmode for the arguments or results corresponding to the "tf" in the name?
On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > This patch is the beginning step to switching the PowerPC long double support > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > will be necessary to have this patch or a similar patch to allow the GLIBC team > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > out, we can decide to switch the default. It is likely, the default will only > be switched on the 64-bit little endian PowerPC systems, when a distribution > goes through a major level, such that they can contemplate major changes. I would hope the default changes for BE systems at the same time (at least those with VSX, but ideally *all*). > If you do not use the configuration option --with-long-double-format=ieee or > --with-long-double-format=ibm, the system will not build multilibs, and just > build normal libraries with the default set to IBM extended double. If you do > use either of the switches, and allow multilibs, it will build two sets of > multilibs, one for -mabi=ieeelongdouble and one for -mabi=ibmlongdouble. Huh. Why not always, then? There already is an option to turn off multilibs, for people who really really want that. Segher
On Mon, Jan 08, 2018 at 10:17:06AM -0600, Segher Boessenkool wrote: > On Thu, Jan 04, 2018 at 06:05:55PM -0500, Michael Meissner wrote: > > This patch is the beginning step to switching the PowerPC long double support > > from IBM extended double to IEEE 128-bit floating point on PowerPC servers. It > > will be necessary to have this patch or a similar patch to allow the GLIBC team > > to begin their modifications in GLIBC 2.28, so that by the time GCC 9 comes > > out, we can decide to switch the default. It is likely, the default will only > > be switched on the 64-bit little endian PowerPC systems, when a distribution > > goes through a major level, such that they can contemplate major changes. > > I would hope the default changes for BE systems at the same time (at > least those with VSX, but ideally *all*). Note, the change has to be on a system by system basis. We will need to support distributions that use the IBM extended double for the long double format, and we will need to support distributions for the IEEE 128-bit format. It all depends on what the host system uses. While the work can be done, I don't know of any BE distribution that will be using GCC 8 as their main compiler. > > If you do not use the configuration option --with-long-double-format=ieee or > > --with-long-double-format=ibm, the system will not build multilibs, and just > > build normal libraries with the default set to IBM extended double. If you do > > use either of the switches, and allow multilibs, it will build two sets of > > multilibs, one for -mabi=ieeelongdouble and one for -mabi=ibmlongdouble. > > Huh. Why not always, then? There already is an option to turn off > multilibs, for people who really really want that. I'm trying not to surprise people building compilers for a setup that does not work. In the GCC 9 timeframe, when there is GLIBC support for it, we can make it default (assuming we keep the multilibs). It is a chicken and egg problem. Real users (as opposed to GCC and GLIBC developers) would need GLIBC 2.28 in order to use the IEEE multilib. But if we don't provide the switch or multilib as an option, it makes the GLIBC work harder. I suspect that libstc++-v3 may be more of an issue than GLIBC, since we have people starting to look at the GLIBC work, but we can't really do anything about libstdc++-v3 until we have a GLIBC.
To answer some of my own questions about how this works (or doesn't work): There are two different types in libgcc called TFtype, one in quad-float128.h and one in libgcc2.h. The one in quad-float128.h is mapped to KFmode in the case where TFmode is IBM long double, so functions such as __mulkc3 do get the correct types. As far as I can tell, functions such as __multf3, and libgcc2.c TFmode functions in general, get the version of TFtype from libgcc2.h (which is always of mode TFmode). So I still don't see how you ensure all those functions do use IBM long double when IEEE long double is the default (but have not tested a build with IEEE long double as default). (And __powikf2 doesn't even exist, but is needed for __builtin_powil to work properly in the IEEE long double case.) I have confirmed with testing that _Complex long double multiplication with -mabi=ieeelongdouble still uses __multc3, although it needs to use __mulkc3, and, likewise, _Complex long double division with -mabi=ieeelongdouble wrongly uses __divtc3 but should be using __divkc3.
This is my current multilib version support for migrating PowerPC servers from using IBM extended double as the long double type to IEEE 128-bit floating point. I have built both little endian and big endian PowerPC toolchains without the options, and it works with no regressions. I have also built a PowerPC little endian multlib toolchain (with IBM extended double as the default) and it worked, once I remembered to add the --with-system-zlib option. All of the other patches have been broken out of this patch and submitted (and now comitteed -- thanks Segher), and this patch just adds the option multlib support for PowerPC little endian. I ran out of time to add the PowerPC big endian multilib support (as it has to merge with 64/32-bit multilibs, and it also can only be enabled if the compiler is compiled using --with-cpu with at least power7). Some changes from the last change based on comments I got: 1) The lib64 directory is the directory that holds the default libraries. If you configure the default to be IEEE 128-bit, then those libraries are put into lib64. As Bill Schmidt said in an internal meeting, that is required by the ABI. Other languages should work normally, assuming they don't use long double. If they do use long double and use other libraries than libc/libm, they may need to use an -L -rpath optiosn to point to the old libraries. I'm sure as we get into modifying GLIBC 2.28, we will discover new things. 2) If you configure the compiler so that IBM long double is the default, the IEEE libraries are in lib64/ieee128. If you configure the compiler so that IEEE is the default, the IBM extended double libraries are in lib64/ibm128. I assume if we do a big endian port, we would use lib/ieee128 and lib/ibm128. 3) Tulio says that he believes that the GLIBC libraries will be able to handle the switch with a single library. However, it is not clear to me that other libraries like libstdc++, boost, etc. would be easy to add the necessary support to change the interfaces based on the defines. This is why I think we need multilibs, at least for a transition period. 4) As before, you have to explicitly configure the long double format to enable the multilibs. Particularly with having to create a special version of the Advance Toolchain with the crt/lib files in the alternate directory and use --with-system-zlib, you really don't want to enable the multilibs by default. Can I check this into the trunk? As I post this, there are two previous patches that have not been ack'ed that are not needed to enable the multilibs, but will be needed as we start doing the transition. The patches are: 1) The patch to set .gnu_attribute #4 if you use a long double value but don't do any calls. 2) The patch to document the --with-long-double-format={ieee,ibm} option. It would be useful if I could configure the compiler to look in lib64, if it doesn't find the objects in lib64/ieee128 or lib64/ibm128. But perhaps it is safer if it doesn't, since some things may fall through the cracks. Note, I will be on vacation for the next 4 days, and I will return on Tuesday January 16th, 2018. I will not have access to mail for most of the time. 2018-01-12 Michael Meissner <meissner@linux.vnet.ibm.com> * config.gcc (powerpc*-linux*-*): Add support for 64-bit little endian Linux systems to optionally enable multilibs for selecting the long double type if the user configured an explicit type. * config/rs6000/rs6000.h (TARGET_IEEEQUAD_MULTILIB): Indicate we have no long double multilibs if not defined. * config/rs6000/rs6000.c (rs6000_option_override_internal): Do not warn if the user used -mabi={ieee,ibm}longdouble and we built multilibs for long double. * config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Define as the appropriate multilib option. (MULTILIB_DEFAULTS): Add MULTILIB_DEFAULTS_IEEE to the default multilib options. * config/rs6000/t-ldouble-linux64le-ibm: New configuration files for building long double multilibs. * config/rs6000/t-ldouble-linux64le-ieee: Likewise.
Of course it would be helpful, if I included the patch: 2018-01-12 Michael Meissner <meissner@linux.vnet.ibm.com> * config.gcc (powerpc*-linux*-*): Add support for 64-bit little endian Linux systems to optionally enable multilibs for selecting the long double type if the user configured an explicit type. * config/rs6000/rs6000.h (TARGET_IEEEQUAD_MULTILIB): Indicate we have no long double multilibs if not defined. * config/rs6000/rs6000.c (rs6000_option_override_internal): Do not warn if the user used -mabi={ieee,ibm}longdouble and we built multilibs for long double. * config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Define as the appropriate multilib option. (MULTILIB_DEFAULTS): Add MULTILIB_DEFAULTS_IEEE to the default multilib options. * config/rs6000/t-ldouble-linux64le-ibm: New configuration files for building long double multilibs. * config/rs6000/t-ldouble-linux64le-ieee: Likewise.
On Fri, Jan 12, 2018 at 07:23:37AM -0500, Michael Meissner wrote: > Of course it would be helpful, if I included the patch: Yup :-) > 2018-01-12 Michael Meissner <meissner@linux.vnet.ibm.com> > > * config.gcc (powerpc*-linux*-*): Add support for 64-bit little > endian Linux systems to optionally enable multilibs for selecting > the long double type if the user configured an explicit type. > * config/rs6000/rs6000.h (TARGET_IEEEQUAD_MULTILIB): Indicate we > have no long double multilibs if not defined. > * config/rs6000/rs6000.c (rs6000_option_override_internal): Do not > warn if the user used -mabi={ieee,ibm}longdouble and we built > multilibs for long double. > * config/rs6000/linux64.h (MULTILIB_DEFAULTS_IEEE): Define as the > appropriate multilib option. > (MULTILIB_DEFAULTS): Add MULTILIB_DEFAULTS_IEEE to the default > multilib options. > * config/rs6000/t-ldouble-linux64le-ibm: New configuration files > for building long double multilibs. > * config/rs6000/t-ldouble-linux64le-ieee: Likewise. > + case "${target}:${enable_multilib}:${with_long_double_format}" in > + powerpc64le*:yes:ieee | powerpc64le*:yes:ibm) > + tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1" > + tmake_file="${tmake_file} rs6000/t-ldouble-linux64le-${with_long_double_format}" > + ;; > + *) > + : > + ;; You could just leave out those three lines default (or at least the :). Looks fine I think. Okay for trunk, thanks! Segher
Hi! On Fri, Jan 12, 2018 at 01:46:27AM -0500, Michael Meissner wrote: > This is my current multilib version support for migrating PowerPC servers from > using IBM extended double as the long double type to IEEE 128-bit floating > point. > > I have built both little endian and big endian PowerPC toolchains without the > options, and it works with no regressions. I have also built a PowerPC little > endian multlib toolchain (with IBM extended double as the default) and it > worked, once I remembered to add the --with-system-zlib option. > > All of the other patches have been broken out of this patch and submitted (and > now comitteed -- thanks Segher), and this patch just adds the option multlib > support for PowerPC little endian. I ran out of time to add the PowerPC big > endian multilib support (as it has to merge with 64/32-bit multilibs, and it > also can only be enabled if the compiler is compiled using --with-cpu with at > least power7). Right -- it will be much simpler if we can use ieee128 also without VSX. > Some changes from the last change based on comments I got: > > 1) The lib64 directory is the directory that holds the default libraries. If > you configure the default to be IEEE 128-bit, then those libraries are put into > lib64. As Bill Schmidt said in an internal meeting, that is required by the > ABI. Other languages should work normally, assuming they don't use long > double. If they do use long double and use other libraries than libc/libm, > they may need to use an -L -rpath optiosn to point to the old libraries. I'm > sure as we get into modifying GLIBC 2.28, we will discover new things. "Brace yourself, winter is coming". > 2) If you configure the compiler so that IBM long double is the default, the > IEEE libraries are in lib64/ieee128. If you configure the compiler so that > IEEE is the default, the IBM extended double libraries are in lib64/ibm128. I > assume if we do a big endian port, we would use lib/ieee128 and lib/ibm128. For the 32-bit libs? Yeah. > 3) Tulio says that he believes that the GLIBC libraries will be able to handle > the switch with a single library. However, it is not clear to me that other > libraries like libstdc++, boost, etc. would be easy to add the necessary > support to change the interfaces based on the defines. This is why I think we > need multilibs, at least for a transition period. > > 4) As before, you have to explicitly configure the long double format to enable > the multilibs. Particularly with having to create a special version of the > Advance Toolchain with the crt/lib files in the alternate directory and use > --with-system-zlib, you really don't want to enable the multilibs by default. > > Can I check this into the trunk? > > As I post this, there are two previous patches that have not been ack'ed that > are not needed to enable the multilibs, but will be needed as we start doing > the transition. The patches are: > > 1) The patch to set .gnu_attribute #4 if you use a long double value but don't > do any calls. > > 2) The patch to document the --with-long-double-format={ieee,ibm} option. > > It would be useful if I could configure the compiler to look in lib64, if it > doesn't find the objects in lib64/ieee128 or lib64/ibm128. But perhaps it is > safer if it doesn't, since some things may fall through the cracks. I think it always does that? If not, get back to me when you need this? > Note, I will be on vacation for the next 4 days, and I will return on Tuesday > January 16th, 2018. I will not have access to mail for most of the time. Enjoy your vacation! Segher
Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 256120) +++ gcc/configure.ac (working copy) @@ -5885,6 +5885,30 @@ if test x$gcc_cv_target_ldbl128 = xyes; [Define if TFmode long double should be the default]) fi +# Check if TFmode long double target should use the IBM extended double or IEEE +# 128-bit floating point formats if long doubles are 128-bits long. The long +# double type can only be switched on powerpc64 bit Linux systems where VSX is +# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in +# liggcc. +AC_ARG_WITH([long-double-format], + [AS_HELP_STRING([--with-long-double-format={ieee,ibm}] + [Specify whether PowerPC long double uses IEEE or IBM format])],[ +case "$target:$with_cpu:$with_long_double_format" in + powerpc*-*-linux*:power[789]:ieee | powerpc*-*-linux*:power[1-9][0-9]+:ieee | \ + powerpc*-*-linux*:power[789]:ibm | powerpc*-*-linux*:power[1-9][0-9]+:ibm | \ + powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm) + ;; + powerpc*-*-linux*:power[789]:* | powerpc*-*-linux*:power[1-9][0-9]+:* | \ + powerpc64le-*-linux*:*:*) + AC_MSG_ERROR([--with-long-double-format argument should be ibm or ieee]) + ;; + *) + AC_MSG_ERROR([Configure option --with-long-double-format is only supported \ +for PowerPC VSX Linux systems]) + ;; +esac], + []) + # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP # values in the TCB. Currently, only GLIBC 2.23 and later support this. gcc_cv_libc_provides_hwcap_in_tcb=no Index: gcc/configure =================================================================== --- gcc/configure (revision 256120) +++ gcc/configure (working copy) @@ -945,6 +945,7 @@ enable_linker_build_id enable_libssp enable_default_ssp with_long_double_128 +with_long_double_format with_gc with_system_zlib enable_maintainer_mode @@ -1738,6 +1739,9 @@ Optional Packages: --with-glibc-version=M.N assume GCC used with glibc version M.N or later --with-long-double-128 use 128-bit long double by default + --with-long-double-format={ieee,ibm} + Specify whether PowerPC long double uses IEEE or IBM format + --with-gc={page,zone} this option is not supported anymore. It used to choose the garbage collection mechanism to use with the compiler @@ -18442,7 +18446,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18445 "configure" +#line 18449 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18548,7 +18552,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18551 "configure" +#line 18555 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -29185,6 +29189,32 @@ $as_echo "#define TARGET_DEFAULT_LONG_DO fi +# Check if TFmode long double target should use the IBM extended double or IEEE +# 128-bit floating point formats if long doubles are 128-bits long. The long +# double type can only be switched on powerpc64 bit Linux systems where VSX is +# supported. Other PowerPC systems do not build the IEEE 128-bit emulator in +# liggcc. + +# Check whether --with-long-double-format was given. +if test "${with_long_double_format+set}" = set; then : + withval=$with_long_double_format; +case "$target:$with_cpu:$with_long_double_format" in + powerpc*-*-linux*:power789:ieee | powerpc*-*-linux*:power1-90-9+:ieee | \ + powerpc*-*-linux*:power789:ibm | powerpc*-*-linux*:power1-90-9+:ibm | \ + powerpc64le-*-linux*:*:ieee | powerpc64le-*-linux*:*:ibm) + ;; + powerpc*-*-linux*:power789:* | powerpc*-*-linux*:power1-90-9+:* | \ + powerpc64le-*-linux*:*:*) + as_fn_error "--with-long-double-format argument should be ibm or ieee" "$LINENO" 5 + ;; + *) + as_fn_error "Configure option --with-long-double-format is only supported \ +for PowerPC VSX Linux systems" "$LINENO" 5 + ;; +esac +fi + + # Check if the target LIBC supports exporting the AT_PLATFORM and AT_HWCAP # values in the TCB. Currently, only GLIBC 2.23 and later support this. gcc_cv_libc_provides_hwcap_in_tcb=no Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (revision 256120) +++ gcc/config.gcc (working copy) @@ -4392,6 +4392,24 @@ case "${target}" in exit 1 fi fi + + # Set up the default long double format. Only enable the + # IEEE/IBM multilibs if the user explicitly set the long double + # format and did not do --disable-multilib. + if test x$with_long_double_format = xieee; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=1" + if test x$enable_multilib = xyes; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1" + tmake_file="${tmake_file} rs6000/t-ldouble" + fi + + elif test x$with_long_double_format = xibm; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_DEFAULT=0" + if test x$enable_multilib = xyes; then + tm_defines="${tm_defines} TARGET_IEEEQUAD_MULTILIB=1" + tmake_file="${tmake_file} rs6000/t-ldouble" + fi + fi ;; s390*-*-*) Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 256120) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -437,11 +437,13 @@ extern const char *host_detect_local_cpu Similarly IFmode is the IBM long double format even if the default is IEEE 128-bit. Don't allow IFmode if -msoft-float. */ #define FLOAT128_IEEE_P(MODE) \ - ((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + ((TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 \ + && ((MODE) == TFmode || (MODE) == TCmode)) \ || ((MODE) == KFmode) || ((MODE) == KCmode)) #define FLOAT128_IBM_P(MODE) \ - ((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \ + ((!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128 \ + && ((MODE) == TFmode || (MODE) == TCmode)) \ || (TARGET_HARD_FLOAT && ((MODE) == IFmode || (MODE) == ICmode))) /* Helper macros to say whether a 128-bit floating point type can go in a @@ -562,6 +564,12 @@ extern int rs6000_vector_align[]; #define TARGET_ALTIVEC_ABI rs6000_altivec_abi #define TARGET_LDBRX (TARGET_POPCNTD || rs6000_cpu == PROCESSOR_CELL) +/* Define as 1 if we support multilibs for switching long double between IEEE + 128-bit floating point and IBM extended double. */ +#ifndef TARGET_IEEEQUAD_MULTILIB +#define TARGET_IEEEQUAD_MULTILIB 0 +#endif + /* ISA 2.01 allowed FCFID to be done in 32-bit, previously it was 64-bit only. Enable 32-bit fcfid's on any of the switches for newer ISA machines or XILINX. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 256120) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -4600,11 +4600,15 @@ rs6000_option_override_internal (bool gl systems will also set long double to be IEEE 128-bit. AIX and Darwin explicitly redefine TARGET_IEEEQUAD and TARGET_IEEEQUAD_DEFAULT to 0, so those systems will not pick up this default. Warn if the user changes the - default unless -Wno-psabi. */ + default unless either the user used the -Wno-psabi option, or the compiler + was built to enable multilibs to switch between the two long double + types. */ if (!global_options_set.x_rs6000_ieeequad) rs6000_ieeequad = TARGET_IEEEQUAD_DEFAULT; - else if (rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT && TARGET_LONG_DOUBLE_128) + else if (!TARGET_IEEEQUAD_MULTILIB + && rs6000_ieeequad != TARGET_IEEEQUAD_DEFAULT + && TARGET_LONG_DOUBLE_128) { static bool warned_change_long_double; if (!warned_change_long_double) @@ -11424,7 +11428,9 @@ rs6000_must_pass_in_stack (machine_mode static inline bool is_complex_IBM_long_double (machine_mode mode) { - return mode == ICmode || (!TARGET_IEEEQUAD && mode == TCmode); + return mode == ICmode || (!TARGET_IEEEQUAD + && TARGET_LONG_DOUBLE_128 + && mode == TCmode); } /* Whether ABI_V4 passes MODE args to a function in floating point Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (revision 256120) +++ gcc/config/rs6000/rs6000-c.c (working copy) @@ -708,7 +708,18 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi builtin_define ("__LONGDOUBLE128"); if (TARGET_IEEEQUAD) - builtin_define ("__LONG_DOUBLE_IEEE128__"); + { + /* Older versions of GLIBC used __attribute__((__KC__)) to create the + IEEE 128-bit floating point complex type for C++ (which does not + support _Float128 _Complex). If the default for long double is + IEEE 128-bit mode, the library would need to use + __attribute__((__TC__)) instead. Defining __KF__ and __KC__ + is a stop-gap to build with the older libraries, until we + get an updated library. */ + builtin_define ("__LONG_DOUBLE_IEEE128__"); + builtin_define ("__KF__=__TF__"); + builtin_define ("__KC__=__TC__"); + } else builtin_define ("__LONG_DOUBLE_IBM128__"); } Index: gcc/config/rs6000/linux64.h =================================================================== --- gcc/config/rs6000/linux64.h (revision 256120) +++ gcc/config/rs6000/linux64.h (working copy) @@ -245,11 +245,23 @@ extern int dot_symbols; #define DYNAMIC_LINKER_PREFIX "" #endif +#if TARGET_IEEEQUAD_MULTILIB +#if TARGET_IEEEQUAD_DEFAULT +#define MULTILIB_DEFAULTS_IEEE , "mabi=ieeelongdouble" + +#else /* TARGET_IEEEQUAD_DEFAULT. */ +#define MULTILIB_DEFAULTS_IEEE , "mabi=ibmlongdouble" +#endif /* TARGET_IEEEQUAD_DEFAULT. */ + +#else /* TARGET_IEEEQUAD_MULTILIB. */ +#define MULTILIB_DEFAULTS_IEEE +#endif /* TARGET_IEEEQUAD_MULTILIB. */ + #undef MULTILIB_DEFAULTS #if DEFAULT_ARCH64_P -#define MULTILIB_DEFAULTS { "m64" } +#define MULTILIB_DEFAULTS { "m64" MULTILIB_DEFAULTS_IEEE } #else -#define MULTILIB_DEFAULTS { "m32" } +#define MULTILIB_DEFAULTS { "m32" MULTILIB_DEFAULTS_IEEE } #endif /* Split stack is only supported for 64 bit, and requires glibc >= 2.18. */ Index: gcc/config/rs6000/t-ldouble =================================================================== --- gcc/config/rs6000/t-ldouble (revision 0) +++ gcc/config/rs6000/t-ldouble (revision 0) @@ -0,0 +1,24 @@ +# Copyright (C) 2017 Free Software Foundation, Inc. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GCC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# Enable building IEEE 128-bit floating point multilibs on a system that +# defaults to IBM extended double floating point. +MULTILIB_OPTIONS += mabi=ibmlongdouble/mabi=ieeelongdouble +MULTILIB_DIRNAMES += ibm128 ieee128 +MULTILIB_OSDIRNAMES += mabi.ibmlongdouble=../lib64 mabi.ieeelongdouble=../ieee64 ../lib64 + Index: libgcc/config/rs6000/quad-float128.h =================================================================== --- libgcc/config/rs6000/quad-float128.h (revision 256120) +++ libgcc/config/rs6000/quad-float128.h (working copy) @@ -51,12 +51,7 @@ typedef __complex float TCtype __attribu #include <quad.h> -#ifdef __LONG_DOUBLE_IEEE128__ -#define IBM128_TYPE __ibm128 - -#else -#define IBM128_TYPE long double -#endif +#define IBM128_TYPE __ibm128 /* Add prototypes of the library functions created. In case the appropriate int/long types are not declared in scope by the time quad.h is included, @@ -185,7 +180,7 @@ union ibm128_union { #define CVT_FLOAT128_TO_IBM128(RESULT, VALUE) \ { \ double __high, __low; \ - __float128 __value = (VALUE); \ + TFtype __value = (VALUE); \ union ibm128_union u; \ \ __high = (double) __value; \ @@ -196,7 +191,7 @@ union ibm128_union { { \ double __high_temp; \ \ - __low = (double) (__value - (__float128) __high); \ + __low = (double) (__value - (TFtype) __high); \ /* Renormalize low/high and move them into canonical IBM long \ double form. */ \ __high_temp = __high + __low; \ @@ -220,13 +215,13 @@ union ibm128_union { \ /* Handle the special cases of NAN and infinity. */ \ if (__builtin_isnan (__high) || __builtin_isinf (__high)) \ - RESULT = (__float128) __high; \ + RESULT = (TFtype) __high; \ \ /* If low is 0.0, there no need to do the add. In addition, \ avoiding the add produces the correct sign if high is -0.0. */ \ else if (__low == 0.0) \ - RESULT = (__float128) __high; \ + RESULT = (TFtype) __high; \ \ else \ - RESULT = ((__float128) __high) + ((__float128) __low); \ + RESULT = ((TFtype) __high) + ((TFtype) __low); \ } Index: libgcc/config/rs6000/ibm-ldouble.c =================================================================== --- libgcc/config/rs6000/ibm-ldouble.c (revision 256120) +++ libgcc/config/rs6000/ibm-ldouble.c (working copy) @@ -56,6 +56,15 @@ see the files COPYING3 and COPYING.RUNTI #define nonfinite(a) unlikely (! isless (fabs (a), inf ())) +/* If we have __float128/_Float128, use __ibm128 instead of long double. On + other systems, use long double, because __ibm128 might not have been + created. */ +#ifdef __FLOAT128__ +#define IBM128_TYPE __ibm128 +#else +#define IBM128_TYPE long double +#endif + /* Define ALIASNAME as a strong alias for NAME. */ # define strong_alias(name, aliasname) _strong_alias(name, aliasname) # define _strong_alias(name, aliasname) \ @@ -65,10 +74,10 @@ see the files COPYING3 and COPYING.RUNTI but GCC currently generates poor code when a union is used to turn a long double into a pair of doubles. */ -long double __gcc_qadd (double, double, double, double); -long double __gcc_qsub (double, double, double, double); -long double __gcc_qmul (double, double, double, double); -long double __gcc_qdiv (double, double, double, double); +IBM128_TYPE __gcc_qadd (double, double, double, double); +IBM128_TYPE __gcc_qsub (double, double, double, double); +IBM128_TYPE __gcc_qmul (double, double, double, double); +IBM128_TYPE __gcc_qdiv (double, double, double, double); #if defined __ELF__ && defined SHARED \ && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__)) @@ -88,17 +97,17 @@ __asm__ (".symver __gcc_qadd,_xlqadd@GCC ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4"); #endif -/* Combine two 'double' values into one 'long double' and return the result. */ -static inline long double +/* Combine two 'double' values into one 'IBM128_TYPE' and return the result. */ +static inline IBM128_TYPE pack_ldouble (double dh, double dl) { -#if defined (__LONG_DOUBLE_128__) \ +#if defined (__LONG_DOUBLE_128__) && defined (__LONG_DOUBLE_IBM128__) \ && !(defined (_SOFT_FLOAT) || defined (__NO_FPRS__)) return __builtin_pack_longdouble (dh, dl); #else union { - long double ldval; + IBM128_TYPE ldval; double dval[2]; } x; x.dval[0] = dh; @@ -107,8 +116,8 @@ pack_ldouble (double dh, double dl) #endif } -/* Add two 'long double' values and return the result. */ -long double +/* Add two 'IBM128_TYPE' values and return the result. */ +IBM128_TYPE __gcc_qadd (double a, double aa, double c, double cc) { double xh, xl, z, q, zz; @@ -147,7 +156,7 @@ __gcc_qadd (double a, double aa, double return pack_ldouble (xh, xl); } -long double +IBM128_TYPE __gcc_qsub (double a, double b, double c, double d) { return __gcc_qadd (a, b, -c, -d); @@ -157,7 +166,7 @@ __gcc_qsub (double a, double b, double c static double fmsub (double, double, double); #endif -long double +IBM128_TYPE __gcc_qmul (double a, double b, double c, double d) { double xh, xl, t, tau, u, v, w; @@ -181,7 +190,7 @@ __gcc_qmul (double a, double b, double c tau += v + w; /* Add in other second-order terms. */ u = t + tau; - /* Construct long double result. */ + /* Construct IBM128_TYPE result. */ if (nonfinite (u)) return u; xh = u; @@ -189,7 +198,7 @@ __gcc_qmul (double a, double b, double c return pack_ldouble (xh, xl); } -long double +IBM128_TYPE __gcc_qdiv (double a, double b, double c, double d) { double xh, xl, s, sigma, t, tau, u, v, w; @@ -226,7 +235,7 @@ __gcc_qdiv (double a, double b, double c tau = ((v-sigma)+w)/c; /* Correction to t. */ u = t + tau; - /* Construct long double result. */ + /* Construct IBM128_TYPE result. */ if (nonfinite (u)) return u; xh = u; @@ -236,32 +245,32 @@ __gcc_qdiv (double a, double b, double c #if defined (_SOFT_DOUBLE) && defined (__LONG_DOUBLE_128__) -long double __gcc_qneg (double, double); +IBM128_TYPE __gcc_qneg (double, double); int __gcc_qeq (double, double, double, double); int __gcc_qne (double, double, double, double); int __gcc_qge (double, double, double, double); int __gcc_qle (double, double, double, double); -long double __gcc_stoq (float); -long double __gcc_dtoq (double); +IBM128_TYPE __gcc_stoq (float); +IBM128_TYPE __gcc_dtoq (double); float __gcc_qtos (double, double); double __gcc_qtod (double, double); int __gcc_qtoi (double, double); unsigned int __gcc_qtou (double, double); -long double __gcc_itoq (int); -long double __gcc_utoq (unsigned int); +IBM128_TYPE __gcc_itoq (int); +IBM128_TYPE __gcc_utoq (unsigned int); extern int __eqdf2 (double, double); extern int __ledf2 (double, double); extern int __gedf2 (double, double); -/* Negate 'long double' value and return the result. */ -long double +/* Negate 'IBM128_TYPE' value and return the result. */ +IBM128_TYPE __gcc_qneg (double a, double aa) { return pack_ldouble (-a, -aa); } -/* Compare two 'long double' values for equality. */ +/* Compare two 'IBM128_TYPE' values for equality. */ int __gcc_qeq (double a, double aa, double c, double cc) { @@ -272,7 +281,7 @@ __gcc_qeq (double a, double aa, double c strong_alias (__gcc_qeq, __gcc_qne); -/* Compare two 'long double' values for less than or equal. */ +/* Compare two 'IBM128_TYPE' values for less than or equal. */ int __gcc_qle (double a, double aa, double c, double cc) { @@ -283,7 +292,7 @@ __gcc_qle (double a, double aa, double c strong_alias (__gcc_qle, __gcc_qlt); -/* Compare two 'long double' values for greater than or equal. */ +/* Compare two 'IBM128_TYPE' values for greater than or equal. */ int __gcc_qge (double a, double aa, double c, double cc) { @@ -294,35 +303,35 @@ __gcc_qge (double a, double aa, double c strong_alias (__gcc_qge, __gcc_qgt); -/* Convert single to long double. */ -long double +/* Convert single to IBM128_TYPE. */ +IBM128_TYPE __gcc_stoq (float a) { return pack_ldouble ((double) a, 0.0); } -/* Convert double to long double. */ -long double +/* Convert double to IBM128_TYPE. */ +IBM128_TYPE __gcc_dtoq (double a) { return pack_ldouble (a, 0.0); } -/* Convert long double to single. */ +/* Convert IBM128_TYPE to single. */ float __gcc_qtos (double a, double aa __attribute__ ((__unused__))) { return (float) a; } -/* Convert long double to double. */ +/* Convert IBM128_TYPE to double. */ double __gcc_qtod (double a, double aa __attribute__ ((__unused__))) { return a; } -/* Convert long double to int. */ +/* Convert IBM128_TYPE to int. */ int __gcc_qtoi (double a, double aa) { @@ -330,7 +339,7 @@ __gcc_qtoi (double a, double aa) return (int) z; } -/* Convert long double to unsigned int. */ +/* Convert IBM128_TYPE to unsigned int. */ unsigned int __gcc_qtou (double a, double aa) { @@ -338,15 +347,15 @@ __gcc_qtou (double a, double aa) return (unsigned int) z; } -/* Convert int to long double. */ -long double +/* Convert int to IBM128_TYPE. */ +IBM128_TYPE __gcc_itoq (int a) { return __gcc_dtoq ((double) a); } -/* Convert unsigned int to long double. */ -long double +/* Convert unsigned int to IBM128_TYPE. */ +IBM128_TYPE __gcc_utoq (unsigned int a) { return __gcc_dtoq ((double) a); @@ -361,7 +370,7 @@ int __gcc_qunord (double, double, double extern int __eqdf2 (double, double); extern int __unorddf2 (double, double); -/* Compare two 'long double' values for unordered. */ +/* Compare two 'IBM128_TYPE' values for unordered. */ int __gcc_qunord (double a, double aa, double c, double cc) { @@ -389,7 +398,7 @@ fmsub (double a, double b, double c) FP_DECL_Q(V); FP_DECL_D(R); double r; - long double u, x, y, z; + IBM128_TYPE u, x, y, z; FP_INIT_ROUNDMODE; FP_UNPACK_RAW_D (A, a); Index: libgcc/config/rs6000/_mulkc3.c =================================================================== --- libgcc/config/rs6000/_mulkc3.c (revision 256120) +++ libgcc/config/rs6000/_mulkc3.c (working copy) @@ -23,11 +23,11 @@ see the files COPYING3 and COPYING.RUNTI /* This is a temporary specialization of code from libgcc/libgcc2.c. */ -typedef float KFtype __attribute__ ((mode (KF))); -typedef __complex float KCtype __attribute__ ((mode (KC))); +#include "soft-fp.h" +#include "quad-float128.h" -#define COPYSIGN(x,y) __builtin_copysignq (x, y) -#define INFINITY __builtin_infq () +#define COPYSIGN(x,y) __builtin_copysignf128 (x, y) +#define INFINITY __builtin_inff128 () #define isnan __builtin_isnan #define isinf __builtin_isinf @@ -35,13 +35,11 @@ typedef __complex float KCtype __attribu #define __mulkc3 __mulkc3_sw #endif -extern KCtype __mulkc3 (KFtype, KFtype, KFtype, KFtype); - -KCtype -__mulkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +TCtype +__mulkc3 (TFtype a, TFtype b, TFtype c, TFtype d) { - KFtype ac, bd, ad, bc, x, y; - KCtype res; + TFtype ac, bd, ad, bc, x, y; + TCtype res; ac = a * c; bd = b * d; Index: libgcc/config/rs6000/_divkc3.c =================================================================== --- libgcc/config/rs6000/_divkc3.c (revision 256120) +++ libgcc/config/rs6000/_divkc3.c (working copy) @@ -23,12 +23,12 @@ see the files COPYING3 and COPYING.RUNTI /* This is a temporary specialization of code from libgcc/libgcc2.c. */ -typedef float KFtype __attribute__ ((mode (KF))); -typedef __complex float KCtype __attribute__ ((mode (KC))); +#include "soft-fp.h" +#include "quad-float128.h" -#define COPYSIGN(x,y) __builtin_copysignq (x, y) -#define INFINITY __builtin_infq () -#define FABS __builtin_fabsq +#define COPYSIGN(x,y) __builtin_copysignf128 (x, y) +#define INFINITY __builtin_inff128 () +#define FABS __builtin_fabsf128 #define isnan __builtin_isnan #define isinf __builtin_isinf #define isfinite __builtin_isfinite @@ -37,13 +37,11 @@ typedef __complex float KCtype __attribu #define __divkc3 __divkc3_sw #endif -extern KCtype __divkc3 (KFtype, KFtype, KFtype, KFtype); - -KCtype -__divkc3 (KFtype a, KFtype b, KFtype c, KFtype d) +TCtype +__divkc3 (TFtype a, TFtype b, TFtype c, TFtype d) { - KFtype denom, ratio, x, y; - KCtype res; + TFtype denom, ratio, x, y; + TCtype res; /* ??? We can get better behavior from logarithmic scaling instead of the division. But that would mean starting to link libgcc against Index: libgcc/config/rs6000/extendkftf2-sw.c =================================================================== --- libgcc/config/rs6000/extendkftf2-sw.c (revision 256120) +++ libgcc/config/rs6000/extendkftf2-sw.c (working copy) @@ -44,7 +44,7 @@ #endif IBM128_TYPE -__extendkftf2_sw (__float128 value) +__extendkftf2_sw (TFtype value) { IBM128_TYPE ret; Index: libgcc/config/rs6000/trunctfkf2-sw.c =================================================================== --- libgcc/config/rs6000/trunctfkf2-sw.c (revision 256120) +++ libgcc/config/rs6000/trunctfkf2-sw.c (working copy) @@ -43,10 +43,10 @@ #define __trunctfkf2_sw __trunctfkf2 #endif -__float128 +TFtype __trunctfkf2_sw (IBM128_TYPE value) { - __float128 ret; + TFtype ret; CVT_IBM128_TO_FLOAT128 (ret, value); return ret;