Re: libgfortran.so SONAME and powerpc64le-linux ABI changes (2nd patch)

2021-10-30 Thread Thomas Koenig via Fortran

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)

2021-10-30 Thread Jakub Jelinek via Fortran
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)

2021-10-30 Thread Thomas Koenig via Fortran



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)

2021-10-29 Thread Michael Meissner via Fortran
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,