Re: libgfortran.so SONAME and powerpc64le-linux ABI changes (2nd patch)
Hi Jakub, On Sat, Oct 30, 2021 at 11:30:29AM +0200, Thomas Koenig wrote: - Have a compiler switch which selects between IEEE_QP and IBM_QP. This was a suggestion by Steve Lionel formerly of DEC and Intel, and they did that when they had a few floating point formats on the Alpha to choose from. We would then have to specially annotate the KIND=16 library routines, and also maybe indicate the different argument types in module files. Anything else would be user error. They also had the CONVERT options to go with it. Question: Which option would we want to pursue? I actually think the fourth one (the suggestion by Steve Lionel) is the best one. That was the last option I was mentioning in the initial mail https://gcc.gnu.org/pipermail/gcc/2021-October/237478.html Copying it here: Or the last option would be to try to make libgfortran.so.5 ABI compatible with both choices on powerpc64le-linux. From quick skimming of libgfortran, we have lots of generated functions, which use HAVE_GFC_REAL_16 and GFC_REAL_16 etc. macros. So, we could perhaps arrange for the compiler to use r16i or r17 instead of r16 in the names when real(kind=16) is the IEEE quad on powerpc64le and keep using r16 for the IBM double double. That is quite doable. For the *.F90 generated files, one could achieve it by making sure the *r16* files are compiled with -mabi=ibmlongdouble, for *r16i* or *r17* with -mabi=ieeelongdouble and otherwise use kind=16 in those, for *.c generated files the *GFC_* macros could just ensure that it doesn't use long double but __ibm128 or __float128 depending on which one is needed. Yep. But then I see e.g. the io routines to just pass in kind and so switch (kind) // or len { case ...: *(GFC_REAL_*) = ...; } etc. Could we just pretend in the compiler to libgfortran ABI that powerpc64le-linux real(kind=16) is kind 17 and make sure that if anything would actually think it is 17 bytes it uses 16 instead (though, kind=10 on x86-64 or i686 also isn't 10 bytes but 16 or 12, right?). That is not something I would like to have, for purposes of cleanness. We can always switch at run-time to a different function. This branch should be rather well-predicted, and additional execution will be insignificant compared to the rest of the I/O. That solution would most closely match what we do e.g. for C/C++, especially libstdc++ or glibc, we already have an option to select that - -mabi=ibmlongdouble vs. -mabi=ieeelongdouble and default selected during configure. libgfortran would be ABI compatible with both ABIs, but user binaries or libraries wouldn't be. Similarly to C, there is no different mangling of user symbols. Hm, there's a difference. I meant that we can select this at compile time for the user, and we should at least consider adding a flag to the module files if the routine has been compiled for IBM_QP or IEEE_QP. We should not change the mangling of the routine names themselves, I agree. Best regards Thomas
Re: libgfortran.so SONAME and powerpc64le-linux ABI changes (2nd patch)
On Sat, Oct 30, 2021 at 11:30:29AM +0200, Thomas Koenig wrote: > - Have a compiler switch which selects between IEEE_QP and IBM_QP. > This was a suggestion by Steve Lionel formerly of DEC and Intel, > and they did that when they had a few floating point formats on > the Alpha to choose from. We would then have to specially annotate > the KIND=16 library routines, and also maybe indicate the different > argument types in module files. Anything else would be user error. > They also had the CONVERT options to go with it. > > Question: Which option would we want to pursue? I actually think the > fourth one (the suggestion by Steve Lionel) is the best one. That was the last option I was mentioning in the initial mail https://gcc.gnu.org/pipermail/gcc/2021-October/237478.html Copying it here: Or the last option would be to try to make libgfortran.so.5 ABI compatible with both choices on powerpc64le-linux. From quick skimming of libgfortran, we have lots of generated functions, which use HAVE_GFC_REAL_16 and GFC_REAL_16 etc. macros. So, we could perhaps arrange for the compiler to use r16i or r17 instead of r16 in the names when real(kind=16) is the IEEE quad on powerpc64le and keep using r16 for the IBM double double. For the *.F90 generated files, one could achieve it by making sure the *r16* files are compiled with -mabi=ibmlongdouble, for *r16i* or *r17* with -mabi=ieeelongdouble and otherwise use kind=16 in those, for *.c generated files the *GFC_* macros could just ensure that it doesn't use long double but __ibm128 or __float128 depending on which one is needed. But then I see e.g. the io routines to just pass in kind and so switch (kind) // or len { case ...: *(GFC_REAL_*) = ...; } etc. Could we just pretend in the compiler to libgfortran ABI that powerpc64le-linux real(kind=16) is kind 17 and make sure that if anything would actually think it is 17 bytes it uses 16 instead (though, kind=10 on x86-64 or i686 also isn't 10 bytes but 16 or 12, right?). That solution would most closely match what we do e.g. for C/C++, especially libstdc++ or glibc, we already have an option to select that - -mabi=ibmlongdouble vs. -mabi=ieeelongdouble and default selected during configure. libgfortran would be ABI compatible with both ABIs, but user binaries or libraries wouldn't be. Similarly to C, there is no different mangling of user symbols. Jakub
Re: libgfortran.so SONAME and powerpc64le-linux ABI changes (2nd patch)
Hi Michael, It adds target hooks so the back end can overwrite the kind number for types. I made the IBM long double type use KIND=15 instead of KIND=16, and Float128 uses KIND=16 as we've discussed. The tests for long double are still failing, so I suspect we will need some way of signalling about the long double which uses a funky kind (king=15). There is still no conclusion how to deal with the two 16-bit types. I have also asked on the J3 mailing list, and received a few different opinions and options as well. We can: - Support KIND=16 == IEEE_QP only in the compiler, and supply a CONVERT option from IBM_QP to IEEE_QP only. People who would need the old format (why anybody would do that, I have no idea, but some may) would have to use the old compiler. - Support KIND=16 == IEEE_QP and KIND=15 = IBM_QP in the compiler, and implement SELECTED_REAL_KIND according to the Fortran standard. This would mean that people who put in a precision of 20 digits as a shorthand for REAL(KIND=16) will get the old version. This will lead to endless confusion, and penalize people who used SELECTED_REAL_KIND, so it should be avoided. - Support KIND=16 == IEEE_QP and KIND=15 = IBM_QP in the compiler, and have SELECTED_REAL_KIND return 16 for anything above double precision. This would actually violate the Fortran standard, and has been generally viewed by J3 as not a good idea. It would, however, work well for most users. Those who actually need IBM_QP would have to specify it specifically. - Have a compiler switch which selects between IEEE_QP and IBM_QP. This was a suggestion by Steve Lionel formerly of DEC and Intel, and they did that when they had a few floating point formats on the Alpha to choose from. We would then have to specially annotate the KIND=16 library routines, and also maybe indicate the different argument types in module files. Anything else would be user error. They also had the CONVERT options to go with it. Question: Which option would we want to pursue? I actually think the fourth one (the suggestion by Steve Lionel) is the best one. Other opinions? Best regards Thomas
Re: libgfortran.so SONAME and powerpc64le-linux ABI changes (2nd patch)
This patch replaces the first patch. Instead of disallowing long double and only dealing with float128 types, this patch tries to accommodate the two. It adds target hooks so the back end can overwrite the kind number for types. I made the IBM long double type use KIND=15 instead of KIND=16, and Float128 uses KIND=16 as we've discussed. The tests for long double are still failing, so I suspect we will need some way of signalling about the long double which uses a funky kind (king=15). Again, this patch may be completely wild and crazy, as I don't really grok the Fortran internals. But perhaps it will help somebody to take the concepts and come up with a more workable solution. Note, the fleshing out of full F128 support is only partially done. I discovered that we don't have a complete set of FLOAT128 built-in functions defined, so I couldn't just add code to DO_DEFINE_MATH_BUILTIN to make every math function have the float128 counterpart declared. Note, that code is probably not used right now, since the float128 support uses the 'q' functions in libquadmath. Too fully utilize the f128 functions, you will need glibc 2.34 or later. > From 80d617264d80eb86806aecb2db5f37adb9b37ff6 Mon Sep 17 00:00:00 2001 > From: Michael Meissner > Date: Fri, 29 Oct 2021 18:35:42 -0400 > Subject: [PATCH] Second patch for PowerPC Fortran KIND=16. This replaces the first patch, and it is a work in progress. This patch adds three target hooks to allow the backend to control the fortran KIND numbers. I have modified the PowerPC back end so that KIND==16 is always IEEE 128-bit on systems support IEEE 128-bit, and KIND=15 is the long double type if long double is IBM 128-bit. gcc/ 2021-10-29 Michael Meissner * config/rs6000/rs6000.c (TARGET_FORTRAN_REAL_KIND_NUMBER): Set target hook. (TARGET_FORTRAN_REAL_KIND_TYPE): Likewise. (TARGET_FORTRAN_REAL_KIND_FLOAT128_P): Likewise. (rs6000_fortran_real_kind_number): New target hook. (rs6000_fortran_real_kind_type): Likewise. (rs6000_fortran_real_kind_float128_p): Likewise. * target.def (fortran_real_kind_number): New target hook. (fortran_real_kind_type): Likewise. (fortran_real_kind_float128_p): Likewise. * targhooks.c (default_fortran_real_kind_number): New default target hooks for Fortran kind support. (default_fortran_real_kind_type): Likewise. (default_fortran_real_kind_float128_p): Likewise. * targhooks.h (default_fortran_real_kind_number): New declaration. (default_fortran_real_kind_type): Likewise. (default_fortran_real_kind_float128_p): Likewise. * tree.h (complex_float128_type_node): New define. * doc/tm.texi.in (TARGET_FORTRAN_REAL_KIND_*): Document new target hooks. * doc/tm.texi: Regenerate. gcc/fortran/ 2021-10-29 Michael Meissner * f95-lang.c (gfc_init_builtin_functions): Flesh out more Float128 support. * trans-types.c (gfc_init_kinds): Add support for using target hooks to allow the backend to control KIND numbers. (gfc_build_real_type): Likewise. (gfc_build_complex_type): Add support for complex Float128. --- gcc/config/rs6000/rs6000.c | 101 + gcc/doc/tm.texi| 17 +++ gcc/doc/tm.texi.in | 6 +++ gcc/fortran/f95-lang.c | 28 ++ gcc/fortran/trans-types.c | 32 gcc/target.def | 22 +++- gcc/targhooks.c| 37 ++ gcc/targhooks.h| 3 ++ gcc/tree.h | 2 + 9 files changed, 236 insertions(+), 12 deletions(-) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 22f5d701908..70595e58ac2 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1787,6 +1787,15 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_INVALID_CONVERSION #define TARGET_INVALID_CONVERSION rs6000_invalid_conversion + +#undef TARGET_FORTRAN_REAL_KIND_NUMBER +#define TARGET_FORTRAN_REAL_KIND_NUMBER rs6000_fortran_real_kind_number + +#undef TARGET_FORTRAN_REAL_KIND_TYPE +#define TARGET_FORTRAN_REAL_KIND_TYPE rs6000_fortran_real_kind_type + +#undef TARGET_FORTRAN_REAL_KIND_FLOAT128_P +#define TARGET_FORTRAN_REAL_KIND_FLOAT128_P rs6000_fortran_real_kind_float128_p /* Processor table. */ @@ -28376,6 +28385,98 @@ rs6000_globalize_decl_name (FILE * stream, tree decl) } #endif + + +/* PowerPC support for Fortran KIND support. Given a MODE, return a kind + number to be used for real modes. If we support IEEE 128-bit, make KIND=16 + always be IEEE 128-bit, and make KIND=15 be the IBM 128-bit double-double + format. */ + +static int +rs6000_fortran_real_kind_number (machine_mode mode) +{ + if (TARGET_FLOAT128_TYPE) +{ + /* If long double is IEEE 128-bit, return 16 for long double and 15 for +__ibm128,