Hi Jakub,

Am 23.06.22 um 14:04 schrieb Jakub Jelinek via Gcc-patches:
Hi!

As mentioned by Joseph in PR105101, glibc 2.26 or later has on x86
(both -m32/-m64), powerpc64le, ia64 and mips support for
*f128 math/complex APIs plus strtof128 and strfromf128, and these APIs allow
us to avoid libquadmath for Fortran purposes on these architectures,
replace *q math/complex APIs, strtof128 instead of strtoflt128 and,
while strfromf128 unfortunately isn't a perfect replacement to
quadmath_snprintf, it can be made to work.

The advantage of this is that when configured against such glibcs
(2.26 is now almost 5 years old), we can avoid linking against an extra shared
library and the math support in glibc is maintained better than libquadmath.

We need both a compiler change (so that for glibc 2.26+ it uses *f128 APIs
instead of *q) and library change.

this is quite an important change in the gfortran ABI, as it will
require recompilation of (library) code using quad precision.
Not that I am particularly affected, but this should be highlighted
for users.

Am I right in assuming that this also effectively fixes PR46539?
(Add -static-libquadmath).

So far lightly tested on x86_64-linux with glibc 2.35 (removed libgfortran
dirs, rebuilt stage3 f951 and make all-target-libgfortran + make
check-gfortran), ok for trunk if it passes full testing?

I did not look into all details, but noticed the following:

--- gcc/fortran/trans-intrinsic.cc.jj   2022-05-16 11:14:57.587427707 +0200
+++ gcc/fortran/trans-intrinsic.cc      2022-06-23 11:42:03.355899271 +0200
@@ -155,7 +155,7 @@ builtin_decl_for_precision (enum built_i
    else if (precision == TYPE_PRECISION (double_type_node))
      i = m->double_built_in;
    else if (precision == TYPE_PRECISION (long_double_type_node)
-          && (!gfc_real16_is_float128
+          && ((!gfc_real16_is_float128 & !gfc_real16_is__Float128)

Shouldn't this be && instead of & ?

               || long_double_type_node != gfc_float128_type_node))
      i = m->long_double_built_in;
    else if (precision == TYPE_PRECISION (gfc_float128_type_node))
@@ -175,7 +175,7 @@ gfc_builtin_decl_for_float_kind (enum bu
  {
    int i = gfc_validate_kind (BT_REAL, kind, false);

-  if (gfc_real_kinds[i].c_float128)
+  if (gfc_real_kinds[i].c_float128 || gfc_real_kinds[i].c__Float128)
      {
        /* For _Float128, the story is a bit different, because we return
         a decl to a library function rather than a built-in.  */
@@ -688,7 +688,7 @@ gfc_build_intrinsic_lib_fndecls (void)
    gfc_intrinsic_map_t *m;
    tree quad_decls[END_BUILTINS + 1];

-  if (gfc_real16_is_float128)
+  if (gfc_real16_is_float128 || gfc_real16_is__Float128)
    {
      /* If we have soft-float types, we create the decls for their
         C99-like library functions.  For now, we only handle _Float128
@@ -739,7 +739,10 @@ gfc_build_intrinsic_lib_fndecls (void)
         builtin_decl_for_float_type(). The others are all constructed by
         gfc_get_intrinsic_lib_fndecl().  */
  #define OTHER_BUILTIN(ID, NAME, TYPE, CONST) \
-  quad_decls[BUILT_IN_ ## ID] = define_quad_builtin (NAME "q", func_ ## TYPE, 
CONST);
+    quad_decls[BUILT_IN_ ## ID]                                                
\
+      = define_quad_builtin (gfc_real16_is__Float128                   \
+                            ? NAME "f128" : NAME "q", func_ ## TYPE,       \
+                            CONST);

  #include "mathbuiltins.def"

@@ -751,8 +754,9 @@ gfc_build_intrinsic_lib_fndecls (void)
      /* There is one built-in we defined manually, because it gets called
         with builtin_decl_for_precision() or builtin_decl_for_float_type()
         even though it is not an OTHER_BUILTIN: it is SQRT.  */
-    quad_decls[BUILT_IN_SQRT] = define_quad_builtin ("sqrtq", func_1, true);
-
+    quad_decls[BUILT_IN_SQRT]
+      = define_quad_builtin (gfc_real16_is__Float128
+                            ? "sqrtf128" : "sqrtq", func_1, true);
    }

    /* Add GCC builtin functions.  */
@@ -775,7 +779,7 @@ gfc_build_intrinsic_lib_fndecls (void)
        m->complex10_decl
          = builtin_decl_explicit (m->complex_long_double_built_in);

-      if (!gfc_real16_is_float128)
+      if (!gfc_real16_is_float128 && !gfc_real16_is__Float128)
        {
          if (m->long_double_built_in != END_BUILTINS)
            m->real16_decl = builtin_decl_explicit (m->long_double_built_in);
@@ -876,6 +880,9 @@ gfc_get_intrinsic_lib_fndecl (gfc_intrin
        else if (gfc_real_kinds[n].c_float128)
        snprintf (name, sizeof (name), "%s%s%s",
                  ts->type == BT_COMPLEX ? "c" : "", m->name, "q");
+      else if (gfc_real_kinds[n].c__Float128)
+       snprintf (name, sizeof (name), "%s%s%s",
+                 ts->type == BT_COMPLEX ? "c" : "", m->name, "f128");
        else
        gcc_unreachable ();
      }
--- gcc/fortran/trans-expr.cc.jj        2022-04-23 10:10:51.146097072 +0200
+++ gcc/fortran/trans-expr.cc   2022-06-23 11:49:31.191964727 +0200
@@ -3582,7 +3582,7 @@ gfc_conv_power_op (gfc_se * se, gfc_expr
                case 3:
                  /* Use the __builtin_powil() only if real(kind=16) is
                     actually the C long double type.  */
-                 if (!gfc_real16_is_float128)
+                 if (!gfc_real16_is_float128 & !gfc_real16_is__Float128)

Likewise.

                    fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
                  break;


You may wish to wait for further comments.

Thanks for the patch!

Harald

Reply via email to