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