Hi!
On Thu, Oct 22, 2020 at 06:03:46PM -0400, Michael Meissner wrote:
> To map the scanf functions, <name> is mapped to __isoc99_<name>ieee128.
Is that correct? What if you are compiling for c90?
> * config/rs6000/rs6000.c (rs6000_mangle_decl_assembler_name): Add
> support for mapping built-in function names for long double
> built-in functions if long double is IEEE 128-bit.
"Map the built-in function names" etc.
> --- a/gcc/config/rs6000/rs6000.c
> +++ b/gcc/config/rs6000/rs6000.c
> @@ -26893,56 +26893,127 @@ rs6000_globalize_decl_name (FILE * stream, tree
> decl)
> library before you can switch the real*16 type at compile time.
>
> We use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change this name. We
> - only do this if the default is that long double is IBM extended double,
> and
> - the user asked for IEEE 128-bit. */
> + only do this transformation if the __float128 type is enabled. This
> + prevents us from doing the transformation on older 32-bit ports that might
> + have enabled using IEEE 128-bit floating point as the default long double
> + type. */
I don't see why that is the right thing to do? You'll have exactly
these same problems on 32-bit!
Hrm, we talked about that before I guess? Do you just need to change
this comment now?
> + default:
> + break;
> + }
That is useless, just leave it out? The end of a switch will always
fall through, and it is normal idiom to use that.
> + /* Update the __builtin_*printf && __builtin_*scanf functions. */
"and" :-)
> + else if (name[len - 1] == 'l')
> + {
> + bool uses_ieee128_p = false;
> + tree type = TREE_TYPE (decl);
> + machine_mode ret_mode = TYPE_MODE (type);
> +
> + /* See if the function returns a IEEE 128-bit floating point type
> or
> + complex type. */
> + if (ret_mode == TFmode || ret_mode == TCmode)
> + uses_ieee128_p = true;
> + else
> {
> - machine_mode arg_mode = TYPE_MODE (arg);
> - if (arg_mode == TFmode || arg_mode == TCmode)
> + function_args_iterator args_iter;
> + tree arg;
(declare that right before the FOREACH)
> +
> + /* See if the function passes a IEEE 128-bit floating point
> type
> + or complex type. */
> + FOREACH_FUNCTION_ARGS (type, arg, args_iter)
> {
> - uses_ieee128_p = true;
> - break;
> + machine_mode arg_mode = TYPE_MODE (arg);
> + if (arg_mode == TFmode || arg_mode == TCmode)
> + {
> + uses_ieee128_p = true;
> + break;
> + }
> }
> }
There is no point in doing all these early-outs in an initialisation
function, making it much harder to read :-(
> + /* If we passed or returned an IEEE 128-bit floating point type,
> + change the name. Use __<name>ieee128, instead of <name>l. */
> + if (uses_ieee128_p)
> + newname = xasprintf ("__%.*sieee128", (int)(len - 1), name);
(int) (len - 1)
Please comment what the - 1 does, and/or what this is for at all. (In
the code / in a comment, not to me, I figured it out after a while.)
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-math.c
> @@ -0,0 +1,567 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi
> -mabi=ieeelongdouble" } */
So why do you need power10_ok? You need power9_ok of course, but why
power10? You can specify -mno-pcrel always.
> + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,2\M} } } */
The " +" should be just a " ".
Not every assembler variant uses plain numbers for registers. That is
not currently an issue of course, but why not just do it right in the
first place :-)
You can do
{\mxsrqpi r?[0-9]+,r?[0-9]+,r?[0-9]+,2\M}
or simpler,
{\mxsrqpi r?\d+,r?\d+,r?\d+,2\M}
or even simpler
{(?n)\mxsrqpi .*,2\M}
(if you don't mind the number of operands in that last case).
> + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,3\M} } } */
(same as above)
> + /* lgammaf128 mentioned previously. */
> + *p++ = BUILTIN1 (lgammal, *q++);
What does that comment mean? Should you have used scan-assembler-times
perhaps?
> + /* { dg-final { scan-assembler {\mxsrqpi +[0-9]+,[0-9]+,[0-9]+,1\M} } } */
(one more)
> + /* remainderf128 mentioned previously. */
> + *p++ = BUILTIN2 (remainderl, *q++, *r++);
(similar to the lgammal case)
> + /* { dg-final { scan-assembler {\m__scalbnieee128\M} } } */
> + *p = BUILTIN2 (scalbl, *q, *r);
(trailing spaces)
> + /* { dg-final { scan-assembler {\m__cabsieee128\M} } } */
> + *p++ = BUILTIN1 (cabsl, *q++);
> +
> + /* inline code. */
> + *p++ = BUILTIN1 (cargl, *q++);
> +
> + /* inline code. */
> + *p++ = BUILTIN1 (cimagl, *q++);
> +
> + /* inline code. */
> + *p = BUILTIN1 (creall, *q);
(trailing spaces)
So no checking here at all? Aww :-)
> + /* inline code. */
> + *p++ = BUILTIN1 (conjl, *q++);
(another)
> + /* __lgammaieee128_r mentioned previously. */
> + *p = BUILTIN2 (lgammal_r, *q, *r);
(-times again; and trailing spaces)
> + /* { dg-final { scan-assembler {\m__scalbnieee128\M} } } */
> + *p = BUILTIN2 (scalbnl, *q, *r);
(guess)
(Many more later. I don't care in a testcase, but just make your editor
not make you do this? :-) )
> +/* Debug main program to determine if the library has all of the mapped
> + external functions. Note, you need a new enough glibc to provide all of
> the
> + f128 functions. */
> +#ifdef DO_MAIN
> +int
> +main (void)
> +{
> + return 0;
> +}
> +#endif
You don't need that #ifdef/#endif, that will always just compile? Oh,
and you don't mention this is to check if linking works, with a manual
command line, aha.
Do you want to make this a link test then? I guess it is hard to detect
whether you have a new enough glibc though :-/
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/float128-longdouble-stdio.c
> @@ -0,0 +1,37 @@
> +/* { dg-require-effective-target ppc_float128_hw } */
> +/* { dg-require-effective-target power10_ok } */
> +/* { dg-options "-mdejagnu-cpu=power9 -mno-pcrel -O2 -Wno-psabi
> -mabi=ieeelongdouble" } */
Same power10_ok issue as the other test.
Segher