[RFC, Fortran] Fix c_float128 and c_float128_complex on targets with 128-bit long double.
Michael Meissner
meissner@linux.ibm.com
Thu Aug 5 17:33:27 GMT 2021
On Wed, Aug 04, 2021 at 02:14:07PM -0600, Sandra Loosemore wrote:
> I was trying last week to run my not-yet-committed TS29113 testsuite
> on a powerpc64le-linux-gnu target and ran into some problems with
> the kind constants c_float128 and c_float128_complex from the
> ISO_C_BINDING module; per the gfortran manual they are supposed to
> represent the kind of the gcc extension type __float128 and the
> corresponding complex type. They were being set to -4 (e.g., not
> supported) instead of 16, although this target does define
> __float128 and real(16) is accepted as a supported type by the
> Fortran front end.
>
> Anyway, the root of the problem is that the definition of these
> constants only looked at gfc_float128_type_node, which only gets set
> if TFmode is not the same type as long_double_type_node. I
> experimented with setting gfc_float128_type_node =
> long_double_type_node but that caused various Bad Things to happen
> elsewhere in code that expected them to be distinct types, so I
> ended up with this minimally intrusive patch that only tweaks the
> definitions of the c_float128 and c_float128_complex constants.
>
> I'm not sure this is completely correct, though. I see PowerPC
> supports 2 different 128-bit encodings and it looks like TFmode/long
> double is mapped onto the one selected by the ABI and/or
> command-line options; that's the only one the Fortran front end
> knows about. All of TFmode, IFmode, and KFmode would map onto kind
> 16 anyway (in spite of having different TYPE_PRECISION values) so
> Fortran wouldn't be able to distinguish them. The thing that
> confuses me is how/when the rs6000 backend defines __float128; it
> looks like the documentation in the GCC manual doesn't agree with
> the code, and I'm not sure what the intended behavior really is. Is
> it possible that __float128 could end up defined but specifying a
> different type than TFmode, and if so is there a target-independent
> way to identify that situation? Can the PowerPC experts help
> straighten me out?
>
> -Sandra
At the moment, we only fully support C and C++ when changing the long double
format (between IEEE 128-bit, IBM 128-bit, and 64-bit) when the compiler is
invoked (and assuming you are using GLIBC 2.32 or newer).
For Fortran and the other languages, the only way to change the floating point
format is to configure the compiler with the '--with-long-double-format=ieee'
configuration option. This makes TFmode use IEEE 128-bit floating point
instead of IBM 128-bit floating point.
It would take somebody familar with the Fortran front end and libraries to make
the same sort of modifications that were made for the C and C++ languages.
Basically you need build libgfortran so that it has support for both floating
point formats, using different names. You would need to modify the fortran
front end to call the alternate functions when the switch is used to change the
floating point format. It might be nice to have a Fortran specific way to
specify which of the two floating point formats are used for REAL*16 (similar
to the use of __float128 and __ibm128 in C/C++, and also _Float128 in just C).
If you are going to do it, good luck.
FWIW, I have built GCC compilers with the alternate floating point format, and
I've been able to run the test suite and compile the Spec 2017 test suite with
it.
Generally to build a bootstrap compiler with the alternate long double
representation I go through the following steps.
1) Make sure you have a GLIBC that supports switching long double
representation (2.32 or new). I tend to use the IBM Advance Toolchain AT
14.0-3 to provide the new library, but if the native GLIBC on your system is
new enough you could use that. I've discovered that there are problems if the
GCC zlib is use, so I use the system zlib. The options I use when configuring
the compiler include:
--with-advance-toolchain=at14.0
--with-system-zlib
--with-native-system-header-dir=/opt/at14.0/include
If you are building and running on a power9 system, it is helpful if you add
the option to set the default CPU to power9, since that way the compiler will
automatically use the hardware IEEE 128-bit instructions that were added in
power9. Otherwise it has to go through a call to do each operation. If you
are running on a power9, we use the ifunc attribute to select modules that are
built to use the hardware instruction.
--with-cpu=power9
2) Build a non-bootstrap compiler with the '--with-long-double-format=ieee'
configuration option, and install it somewhere.
3) With the compiler built in step #2, build the three libraries GCC uses (MPC,
MPFR, and GMP), and install them some place. You need to do this because these
libraries have functions in them with long double arguments. GCC doesn't
actually use the functions with the long double arguments, but you will get a
linker warning about mixing long double floating point type.
4) With the compiler built in step #2 and the libraries built in step #3, build
a non-bootstrap compiler using '--with-long-double-format=ieee' and install
it. You don't need to do this step, but when I was doing the development, I
found it easier to track down problems with the non-bootstrap compiler.
5) If you haven't had any errors, go on to building a full bootstrap version of
the compiler using the compiler built in step #4 for stage1 and the libraries
built in step #2.
--
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.ibm.com, phone: +1 (978) 899-4797
More information about the Fortran
mailing list