[PATCH 0/9] PowerPC: Patches to enable changing the long double default to IEEE 128-bit on little endian PowerPC 64-bit Linux systems
Michael Meissner
meissner@linux.ibm.com
Thu Sep 24 20:20:36 GMT 2020
This series of 9 patches is an attempt to gather together all of the patches
that are needed to be able to configure and build a little endian 64-bit
PowerPC Linux GCC compiler where the defualt long double format uses the IEEE
128-bit representation.
I have created an IBM vendor branch that includes these patches (along the
other outstanding patches that I have for IEEE 128-bit min/max/cmove on
power10, and power10 PCREL_OPT support):
vendors/ibm/ieee-longdouble-001
You will need a new enough GLIBC in order to do this configuration. The
Advance Toolchain AT14.0 from IBM includes the changes in the library that are
needed to build a compiler with this default.
Note, with these patches, we need the libstdc++ work that was begun last year
to be finished and committed. This shows up in trying to build the Spec 2017
511.parest_r (rate) benchmark when long double uses the IEEE representation.
Using the steps outlined below, I have build and bootstraped current GCC
sources, comparing builds where the default long double is the current IBM
extended double to builds where long double uses the IEEE 128-bit
representation. The only difference in C, C++, LTO, and Fortran tests are 3
Fortran tests that either were marked as XFAIL or just failed now pass.
The patches that will be posted include:
#1 Map built-in function names for long double;
#2 Update error messages intermixing the 2 128-bit types;
#3 Fixes libgcc conversions between the 2 128-bit types;
#4 Add support for converting IEEE 128-bit <-> Decimal;
#5 Update tests to run with IEEE 128-bit long double;
#6 Map nanq, nansq, etc. to long double if long double is IEEE;
#7 Update power10 __float128 tests to work with IEEE long double;
#8 Use __float128 in some of the tests instead of __ieee128; (and)
#9 Use __builtin_pack_ieee128 in libgcc if IEEE long double.
I put the following file in the branch:
gcc/config/rs6000/gcc-with-ieee-128bit-longdouble.txt
This is a short memo of how to build a GCC 11 compiler where the long double
type is IEEE 128-bit instead of using the IBM extended double format on the
PowerPC 64-bit little endian Linux environment.
You will likely need the Advance Toolchain AT14.0 library, as it has all of the
changes to support switching the long double default to IEEE 128-bit.
* https://www.ibm.com/support/pages/advance-toolchain-linux-power
You will need a recent version of binutils. I've used the binutils that I
downloaded via git on September 14th, 2020:
* git clone git://sourceware.org/git/binutils-gdb.git
You will need appropriate versions of the gmp, mpfr, and mpc libraries:
* http://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
* http://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
* http://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
Currently, I use --without-ppl --without-cloog --without-isl so I haven't used
those libraries.
I currently disable plug-in support. If you want plug-in support, you will
likely need to build a binutils with the first compiler, to use with the second
and third compilers. If you use a binutils compiled with a compiler where the
long double format is IBM extended double, it may not work.
I found I needed the configuration option --with-system-zlib to avoid some
issues when doing a bootstrap build.
Build the first PowerPC GCC compiler (non-bootstrap) using at least the
following options:
--prefix=<first-gcc-install>
--enable-stage1-languages=c,c++,fortran
--disable-bootstrap
--disable-plugin
--with-long-double-format=ieee
--with-advance-toolchain=at14.0
--with-system-zlib
--with-native-system-header-dir=/opt/at14.0/include
--without-ppl
--without-cloog
--without-isl
Other configuration options that I use but may not affect switching the long
double default include:
--enable-checking
--enable-languages=c,c++,fortran
--enable-stage1-checking
--enable-gnu-indirect-function
--enable-decimal-float
--with-long-double-128
--enable-secureplt
--enable-threads=posix
--enable-__cxa_atexit
--with-as=<as location>
--with-ld=<ld location>
--with-gnu-as=<as location>
--with-gnu-ld=<ld location>
--with-cpu=power9 (or --with-cpu=power8)
Build and install the first compiler.
Configure, build, and install gmp 6.1.0 using the first compiler built above
with following configuration options:
--prefix=<gmp-install>
--enable-static
--disable-shared
--enable-cxx
CPPFLAGS=-fexceptions
Configure, build, and install mpfr 3.1.4 using the first compiler build above
with the following configuration options:
--prefix=<mprf-install>
--enable-static
--disable-shared
--with-gmp=<gmp-install>
Configure, build, and install mpc 1.0.3 using the first compiler build above
with the following configuration options:
--prefix=<mpc-install>
--enable-static
--disable-shared
--with-gmp=<gmp-install>
--with-mpfr=<mpfr-install>
Configure, build, and install the second compiler using the first compiler to
build the second compiler, and using the gmp, mpfr, and mpc libraries built
above. You could skip this step, but I found during development, it was useful
to shake things out before diving into a bootstrap build. The notable
configuration options used are:
--prefix=<second-gcc-install>
--enable-stage1-languages=c,c++,fortran
--disable-bootstrap
--disable-plugin
--with-long-double-format=ieee
--with-system-zlib
--with-advance-toolchain=at14.0
--with-native-system-header-dir=/opt/at14.0/include
--with-gmp=<gmp-install>
--with-mpfr=<mpfr-install>
--with-mpc=<mpc-install>
--without-ppl
--without-cloog
--without-isl
As before, I tend to add these options as well:
--enable-checking
--enable-languages=c,c++,fortran
--enable-stage1-checking
--enable-gnu-indirect-function
--enable-decimal-float
--with-long-double-128
--enable-secureplt
--enable-threads=posix
--enable-__cxa_atexit
--with-as=<as location>
--with-ld=<ld location>
--with-gnu-as=<as location>
--with-gnu-ld=<ld location>
--with-cpu=power9 (or --with-cpu=power8)
Assuming the second compiler builds and installs, now go onto building a
bootstrap third compiler, using the second compiler to build stage1. The
options I used include:
--prefix=<third-gcc-install>
--disable-plugin
--with-long-double-format=ieee
--with-cpu=power9
--with-system-zlib
--with-advance-toolchain=at14.0
--with-native-system-header-dir=/opt/at14.0/include
--with-gmp=<gmp-location>
--with-mpfr=<mpfr-location>
--with-mpc=<mpc-location>
--without-ppl
--without-cloog
--without-isl
As before, I tend to add these options as well:
--enable-languages=c,c++,fortran
--enable-checking
--enable-stage1-checking
--enable-gnu-indirect-function
--enable-decimal-float
--with-long-double-128
--enable-secureplt
--enable-threads=posix
--enable-__cxa_atexit
--with-as=<as location>
--with-ld=<ld location>
--with-gnu-as=<as location>
--with-gnu-ld=<ld location>
--with-cpu=power9 (or --with-cpu=power8)
Three fortran tests that used to fail now succeed:
gfortran.dg/default_format_2.f90 (marked XFAIL)
gfortran.dg/default_format_denormal_2.f90 (marked XFAIL)
gfortran.dg/ieee/large_2.f90 (not marked XFAIL)
I built Spec 2017 rate benchmarks with the newest compiler.
1) The 500.perlbench_r benchmark uses long double in the sv.c module. It
looks like perl uses long double as the universal type in the sv.c
module. There are 2 conversions from double to long double, 1
conversion from long double back to double, and 3 long double
comparisons.
In looking at the sv.c in the Spec 2017 suite, there are a bunch of
#ifdef's to control how perl optimizes the use of long double. The
Spec options disables these #ifdef's, but it is likely these same
#ifdef's are used in the current version of perl used by the
distributions. It is likely that if the long double change is made on
a system wide basis, that the perl configuration will need to be
tweaked to know that long double uses the IEEE 128-bit format.
2) The 510.parest_r benchmark fails to link because there are missing
functions in libstdc++. I'm including a simplification of the error
messages below:
<...>/ld: source/lac/full_matrix.o: in function `dealii::FullMatrix<std::complex<__ieee128> >::ExcNotRegular::print_info(std::ostream&) const':
<...>/include/lac/full_matrix.h:1206: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)'
<...>/ld: source/lac/full_matrix.o: in function `void dealii::LogStream::print<std::complex<__ieee128> >(std::complex<__ieee128> const&)':
<...>/include/base/logstream.h:441: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)'
<...>/ld: source/lac/full_matrix.o: in function `void dealii::FullMatrix<std::complex<__ieee128> >::print<std::ostream>(std::ostream&, unsigned int, unsigned int) const':
<...>/include/lac/full_matrix.h:1499: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)'
<...>/ld: source/lac/full_matrix.o: in function `dealii::FullMatrix<std::complex<__ieee128> >::print_formatted(std::ostream&, unsigned int, bool, unsigned int, char const*, double, double) const':
<...>/include/lac/full_matrix.templates.h:1479: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)'
<...>/ld: source/lac/vector.o: in function `dealii::Vector<std::complex<__ieee128> >::print(std::ostream&, unsigned int, bool, bool) const':
<...>/include/lac/vector.templates.h:800: undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)'
<...>/ld: source/lac/vector.o:<...>/include/lac/vector.templates.h:797: more undefined references to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <__ieee128, char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >, std::complex<__ieee128> const&)' follow
collect2: error: ld returned 1 exit status
With the discusion:
* https://gcc.gnu.org/pipermail/gcc/2020-August/233338.html
the agreement was to continue having essentially two types (& three modes) in
the compiler.
* When long double uses the IEEE 128-bit representation, the type node
for __float128/_Float128 is the same as the type node for long double,
and __ibm128 has a unique node.
* When long double uses the IBM extended double representation (current
behavior), the type node for __ibm128 is the same as for long double,
and __float128/_Float128 have a unique node.
This means that when the long double format changes, C++ libraries cannot mix
functions with the same name using __float128 and long double types. I.e. the
following would generate an error:
class foo {
long double add (long double a, long double b) { return a+b; }
__float128 add (__float128 a, __float128 b) { return a+b; }
};
But C++ users would be able say:
class foo {
long double add (long double a, long double b) { return a+b; }
__ibm128 add (__ibm128 a, __ibm128 b) { return a+b; }
};
The boost library is believed to have both __float128 and long double in a
class. Boost would need to be tweaked so that if the default long double is
IEEE 128-bit, not to enable the explicit __float128 support.
The compiler defines the following macros based on the long double support:
#define __LONG_DOUBLE_IEEE128__ 1 /* if long double is IEEE 128-bit. */
#define __LONG_DOUBLE_IBM128__ 1 /* if long double is IBM 128-bit. */
#define __LONG_DOUBLE_128__ 1 /* if sizeof (long double) == #16. */
--
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 Gcc-patches
mailing list