public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "Kewen.Lin" <linkw@linux.ibm.com>
To: Michael Meissner <meissner@linux.ibm.com>
Cc: gcc-patches@gcc.gnu.org,
	Segher Boessenkool <segher@kernel.crashing.org>,
	David Edelsohn <dje.gcc@gmail.com>,
	Peter Bergner <bergner@linux.ibm.com>,
	Will Schmidt <will_schmidt@vnet.ibm.com>,
	William Seurer <seurer@gcc.gnu.org>
Subject: Re: [PATCH 1/3] Rework 128-bit complex multiply and divide, PR target/107299
Date: Tue, 6 Dec 2022 17:36:54 +0800	[thread overview]
Message-ID: <997752a6-8cd4-abc5-d6e3-2e75eaa37d57@linux.ibm.com> (raw)
In-Reply-To: <Y2HYqx4zLCNCT0Zy@toto.the-meissners.org>

Hi Mike,

Thanks for fixing this!

on 2022/11/2 10:40, Michael Meissner wrote:
> This function reworks how the complex multiply and divide built-in functions are
> done.  Previously we created built-in declarations for doing long double complex
> multiply and divide when long double is IEEE 128-bit.  The old code also did not
> support __ibm128 complex multiply and divide if long double is IEEE 128-bit.
> 
> In terms of history, I wrote the original code just as I was starting to test
> GCC on systems where IEEE 128-bit long double was the default.  At the time, we
> had not yet started mangling the built-in function names as a way to bridge
> going from a system with 128-bit IBM long double to 128-bin IEEE long double.
                                                         ~~~ bit
> 
> The original code depends on there only being two 128-bit types invovled.  With
                                                                  ~~~~~~ involved.
> the next patch in this series, this assumption will no longer be true.  When
> long double is IEEE 128-bit, there will be 2 IEEE 128-bit types (one for the
> explicit __float128/_Float128 type and one for long double).
> 
> The problem is we cannot create two separate built-in functions that resolve to
> the same name.  This is a requirement of add_builtin_function and the C front
> end.  That means for the 3 possible modes (IFmode, KFmode, and TFmode), you can
> only use 2 of them.
> 
> This code does not create the built-in declaration with the changed name.
> Instead, it uses the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change the name
> before it is written out to the assembler file like it now does for all of the
> other long double built-in functions.
> 
> We need to disable using this mapping when we are building libgcc, specifically
> when it is building the floating point 128-bit multiply and divide functions.
> The flag that is used when libgcc is built (-fbuilding-libcc) is only available
> in the C/C++ front ends.  We need to remember that we are building libgcc in the
> rs6000-c.cc support to be able to use this later to decided whether to mangle
> the decl assembler name or not.

IIUC, for the building of floating point 128-bit multiply and divide functions,
the mapping seems still to work fine.  Using the multiply as example here, when
compiling _multc3.o, it's with -mabi=ibmlongdouble, it maps the name with "tc"
which is consistent with what we need.  While compiling _mulkc3*.o, we would
check the macro __LONG_DOUBLE_IEEE128__ and use either KCmode or TCmode, either
of the mapping result would be "kc".

Could you help to elaborate why we need to disable it during libgcc building?

BR,
Kewen

> 
> When I wrote these patches, I discovered that __ibm128 complex multiply and
> divide had originally not been supported if long double is IEEE 128-bit as it
> would generate calls to __mulic3 and __divic3.  I added tests in the testsuite
> to verify that the correct name (i.e. __multc3 and __divtc3) is used in this
> case.
> 
> I tested all 3 patchs for PR target/107299 on:
> 
>     1)	LE Power10 using --with-cpu=power10 --with-long-double-format=ieee
>     2)	LE Power10 using --with-cpu=power10 --with-long-double-format=ibm
>     3)	LE Power9  using --with-cpu=power9  --with-long-double-format=ibm
>     4)	BE Power8  using --with-cpu=power8  --with-long-double-format=ibm
> 
> Once all 3 patches have been applied, we can once again build GCC when long
> double is IEEE 128-bit.  There were no other regressions with these patches.
> Can I check these patches into the trunk?
> 
> 2022-11-01   Michael Meissner  <meissner@linux.ibm.com>
> 
> gcc/
> 
> 	PR target/107299
> 	* config/rs6000/rs6000-c.cc (rs6000_cpu_cpp_builtins): Set
> 	building_libgcc.
> 	* config/rs6000/rs6000.cc (create_complex_muldiv): Delete.
> 	(init_float128_ieee): Delete code to switch complex multiply and divide
> 	for long double.
> 	(complex_multiply_builtin_code): New helper function.
> 	(complex_divide_builtin_code): Likewise.
> 	(rs6000_mangle_decl_assembler_name): Add support for mangling the name
> 	of complex 128-bit multiply and divide built-in functions.
> 	* config/rs6000/rs6000.opt (building_libgcc): New target variable.
> 
> gcc/testsuite/
> 
> 	PR target/107299
> 	* gcc.target/powerpc/divic3-1.c: New test.
> 	* gcc.target/powerpc/divic3-2.c: Likewise.
> 	* gcc.target/powerpc/mulic3-1.c: Likewise.
> 	* gcc.target/powerpc/mulic3-2.c: Likewise.
> ---
>  gcc/config/rs6000/rs6000-c.cc               |   8 ++
>  gcc/config/rs6000/rs6000.cc                 | 110 +++++++++++---------
>  gcc/config/rs6000/rs6000.opt                |   4 +
>  gcc/testsuite/gcc.target/powerpc/divic3-1.c |  18 ++++
>  gcc/testsuite/gcc.target/powerpc/divic3-2.c |  17 +++
>  gcc/testsuite/gcc.target/powerpc/mulic3-1.c |  18 ++++
>  gcc/testsuite/gcc.target/powerpc/mulic3-2.c |  17 +++
>  7 files changed, 145 insertions(+), 47 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/divic3-1.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/divic3-2.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/mulic3-1.c
>  create mode 100644 gcc/testsuite/gcc.target/powerpc/mulic3-2.c
> 
> diff --git a/gcc/config/rs6000/rs6000-c.cc b/gcc/config/rs6000/rs6000-c.cc
> index 56609462629..5c2f3bcee9f 100644
> --- a/gcc/config/rs6000/rs6000-c.cc
> +++ b/gcc/config/rs6000/rs6000-c.cc
> @@ -780,6 +780,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
>        || DEFAULT_ABI == ABI_ELFv2
>        || (DEFAULT_ABI == ABI_AIX && !rs6000_compat_align_parm))
>      builtin_define ("__STRUCT_PARM_ALIGN__=16");
> +
> +  /* Store whether or not we are building libgcc.  This is needed to disable
> +     generating the alternate names for 128-bit complex multiply and divide.
> +     We need to disable generating __multc3, __divtc3, __mulkc3, and __divkc3
> +     when we are building those functions in libgcc.  The variable
> +     flag_building_libgcc is only available for the C family of front-ends.
> +     We set this variable here to disable generating the alternate names.  */
> +  building_libgcc = flag_building_libgcc;
>  }
>  
>  \f
> diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
> index a85d7630b41..cfb6227e27b 100644
> --- a/gcc/config/rs6000/rs6000.cc
> +++ b/gcc/config/rs6000/rs6000.cc
> @@ -11123,26 +11123,6 @@ init_float128_ibm (machine_mode mode)
>      }
>  }
>  
> -/* Create a decl for either complex long double multiply or complex long double
> -   divide when long double is IEEE 128-bit floating point.  We can't use
> -   __multc3 and __divtc3 because the original long double using IBM extended
> -   double used those names.  The complex multiply/divide functions are encoded
> -   as builtin functions with a complex result and 4 scalar inputs.  */
> -
> -static void
> -create_complex_muldiv (const char *name, built_in_function fncode, tree fntype)
> -{
> -  tree fndecl = add_builtin_function (name, fntype, fncode, BUILT_IN_NORMAL,
> -				      name, NULL_TREE);
> -
> -  set_builtin_decl (fncode, fndecl, true);
> -
> -  if (TARGET_DEBUG_BUILTIN)
> -    fprintf (stderr, "create complex %s, fncode: %d\n", name, (int) fncode);
> -
> -  return;
> -}
> -
>  /* Set up IEEE 128-bit floating point routines.  Use different names if the
>     arguments can be passed in a vector register.  The historical PowerPC
>     implementation of IEEE 128-bit floating point used _q_<op> for the names, so
> @@ -11154,32 +11134,6 @@ init_float128_ieee (machine_mode mode)
>  {
>    if (FLOAT128_VECTOR_P (mode))
>      {
> -      static bool complex_muldiv_init_p = false;
> -
> -      /* Set up to call __mulkc3 and __divkc3 under -mabi=ieeelongdouble.  If
> -	 we have clone or target attributes, this will be called a second
> -	 time.  We want to create the built-in function only once.  */
> -     if (mode == TFmode && TARGET_IEEEQUAD && !complex_muldiv_init_p)
> -       {
> -	 complex_muldiv_init_p = true;
> -	 built_in_function fncode_mul =
> -	   (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + TCmode
> -				- MIN_MODE_COMPLEX_FLOAT);
> -	 built_in_function fncode_div =
> -	   (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + TCmode
> -				- MIN_MODE_COMPLEX_FLOAT);
> -
> -	 tree fntype = build_function_type_list (complex_long_double_type_node,
> -						 long_double_type_node,
> -						 long_double_type_node,
> -						 long_double_type_node,
> -						 long_double_type_node,
> -						 NULL_TREE);
> -
> -	 create_complex_muldiv ("__mulkc3", fncode_mul, fntype);
> -	 create_complex_muldiv ("__divkc3", fncode_div, fntype);
> -       }
> -
>        set_optab_libfunc (add_optab, mode, "__addkf3");
>        set_optab_libfunc (sub_optab, mode, "__subkf3");
>        set_optab_libfunc (neg_optab, mode, "__negkf2");
> @@ -28142,6 +28096,25 @@ rs6000_starting_frame_offset (void)
>    return RS6000_STARTING_FRAME_OFFSET;
>  }
>  \f
> +/* Internal function to return the built-in function id for the complex
> +   multiply operation for a given mode.  */
> +
> +static inline built_in_function
> +complex_multiply_builtin_code (machine_mode mode)
> +{
> +  return (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + mode
> +			      - MIN_MODE_COMPLEX_FLOAT);
> +}
> +
> +/* Internal function to return the built-in function id for the complex divide
> +   operation for a given mode.  */
> +
> +static inline built_in_function
> +complex_divide_builtin_code (machine_mode mode)
> +{
> +  return (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + mode
> +			      - MIN_MODE_COMPLEX_FLOAT);
> +}
>  
>  /* On 64-bit Linux and Freebsd systems, possibly switch the long double library
>     function names from <foo>l to <foo>f128 if the default long double type is
> @@ -28160,11 +28133,54 @@ rs6000_starting_frame_offset (void)
>     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.  */
> +   type.
> +
> +   We also use the TARGET_MANGLE_DECL_ASSEMBLER_NAME hook to change the
> +   function names used for complex multiply and divide to the appropriate
> +   names.  */
>  
>  static tree
>  rs6000_mangle_decl_assembler_name (tree decl, tree id)
>  {
> +  /* Handle complex multiply/divide.  For IEEE 128-bit, use __mulkc3 or
> +     __divkc3 and for IBM 128-bit use __multc3 and __divtc3.  */
> +  if (TARGET_FLOAT128_TYPE
> +      && !building_libgcc
> +      && TREE_CODE (decl) == FUNCTION_DECL
> +      && DECL_IS_UNDECLARED_BUILTIN (decl)
> +      && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
> +    {
> +      built_in_function id = DECL_FUNCTION_CODE (decl);
> +      const char *newname = NULL;
> +
> +      if (id == complex_multiply_builtin_code (KCmode))
> +	newname = "__mulkc3";
> +
> +      else if (id == complex_multiply_builtin_code (ICmode))
> +	newname = "__multc3";
> +
> +      else if (id == complex_multiply_builtin_code (TCmode))
> +	newname = (TARGET_IEEEQUAD) ? "__mulkc3" : "__multc3";
> +
> +      else if (id == complex_divide_builtin_code (KCmode))
> +	newname = "__divkc3";
> +
> +      else if (id == complex_divide_builtin_code (ICmode))
> +	newname = "__divtc3";
> +
> +      else if (id == complex_divide_builtin_code (TCmode))
> +	newname = (TARGET_IEEEQUAD) ? "__divkc3" : "__divtc3";
> +
> +      if (newname)
> +	{
> +	  if (TARGET_DEBUG_BUILTIN)
> +	    fprintf (stderr, "Map complex mul/div => %s\n", newname);
> +
> +	  return get_identifier (newname);
> +	}
> +    }
> +
> +  /* Map long double built-in functions if long double is IEEE 128-bit.  */
>    if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
>        && TREE_CODE (decl) == FUNCTION_DECL
>        && DECL_IS_UNDECLARED_BUILTIN (decl)
> diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
> index b63a5d443af..e2de03dda92 100644
> --- a/gcc/config/rs6000/rs6000.opt
> +++ b/gcc/config/rs6000/rs6000.opt
> @@ -100,6 +100,10 @@ unsigned int rs6000_recip_control
>  TargetVariable
>  unsigned int rs6000_debug
>  
> +;; Whether we are building libgcc or not.
> +TargetVariable
> +bool building_libgcc = false
> +
>  ;; Whether to enable the -mfloat128 stuff without necessarily enabling the
>  ;; __float128 keyword.
>  TargetSave
> diff --git a/gcc/testsuite/gcc.target/powerpc/divic3-1.c b/gcc/testsuite/gcc.target/powerpc/divic3-1.c
> new file mode 100644
> index 00000000000..1cc6b1be904
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/divic3-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile { target { powerpc*-*-* } } } */
> +/* { dg-require-effective-target powerpc_p8vector_ok } */
> +/* { dg-require-effective-target longdouble128 } */
> +/* { dg-require-effective-target ppc_float128_sw } */
> +/* { dg-options "-O2 -mpower8-vector -mabi=ieeelongdouble -Wno-psabi" } */
> +
> +/* Check that complex divide generates the right call for __ibm128 when long
> +   double is IEEE 128-bit floating point.  */
> +
> +typedef _Complex long double c_ibm128_t __attribute__((mode(__IC__)));
> +
> +void
> +divide (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r)
> +{
> +  *p = *q / *r;
> +}
> +
> +/* { dg-final { scan-assembler "bl __divtc3" } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/divic3-2.c b/gcc/testsuite/gcc.target/powerpc/divic3-2.c
> new file mode 100644
> index 00000000000..8ff342e0116
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/divic3-2.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target { powerpc*-*-* } } } */
> +/* { dg-require-effective-target powerpc_p8vector_ok } */
> +/* { dg-require-effective-target longdouble128 } */
> +/* { dg-options "-O2 -mpower8-vector -mabi=ibmlongdouble -Wno-psabi" } */
> +
> +/* Check that complex divide generates the right call for __ibm128 when long
> +   double is IBM 128-bit floating point.  */
> +
> +typedef _Complex long double c_ibm128_t __attribute__((mode(__TC__)));
> +
> +void
> +divide (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r)
> +{
> +  *p = *q / *r;
> +}
> +
> +/* { dg-final { scan-assembler "bl __divtc3" } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/mulic3-1.c b/gcc/testsuite/gcc.target/powerpc/mulic3-1.c
> new file mode 100644
> index 00000000000..4cd773c4b06
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/mulic3-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile { target { powerpc*-*-* } } } */
> +/* { dg-require-effective-target powerpc_p8vector_ok } */
> +/* { dg-require-effective-target longdouble128 } */
> +/* { dg-require-effective-target ppc_float128_sw } */
> +/* { dg-options "-O2 -mpower8-vector -mabi=ieeelongdouble -Wno-psabi" } */
> +
> +/* Check that complex multiply generates the right call for __ibm128 when long
> +   double is IEEE 128-bit floating point.  */
> +
> +typedef _Complex long double c_ibm128_t __attribute__((mode(__IC__)));
> +
> +void
> +multiply (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r)
> +{
> +  *p = *q * *r;
> +}
> +
> +/* { dg-final { scan-assembler "bl __multc3" } } */
> diff --git a/gcc/testsuite/gcc.target/powerpc/mulic3-2.c b/gcc/testsuite/gcc.target/powerpc/mulic3-2.c
> new file mode 100644
> index 00000000000..36fe8bc3061
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/powerpc/mulic3-2.c
> @@ -0,0 +1,17 @@
> +/* { dg-do compile { target { powerpc*-*-* } } } */
> +/* { dg-require-effective-target powerpc_p8vector_ok } */
> +/* { dg-require-effective-target longdouble128 } */
> +/* { dg-options "-O2 -mpower8-vector -mabi=ibmlongdouble -Wno-psabi" } */
> +
> +/* Check that complex multiply generates the right call for __ibm128 when long
> +   double is IBM 128-bit floating point.  */
> +
> +typedef _Complex long double c_ibm128_t __attribute__((mode(__TC__)));
> +
> +void
> +multiply (c_ibm128_t *p, c_ibm128_t *q, c_ibm128_t *r)
> +{
> +  *p = *q * *r;
> +}
> +
> +/* { dg-final { scan-assembler "bl __multc3" } } */

  parent reply	other threads:[~2022-12-06  9:37 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-02  2:39 Patch [0/3] for PR target/107299 (GCC does not build on PowerPC when long double is IEEE 128-bit) Michael Meissner
2022-11-02  2:40 ` [PATCH 1/3] Rework 128-bit complex multiply and divide, PR target/107299 Michael Meissner
2022-11-07 15:41   ` Ping: " Michael Meissner
2022-11-29 17:43   ` Ping #2: " Michael Meissner
2022-12-02 17:58   ` Ping #3: " Michael Meissner
2022-12-06  9:36   ` Kewen.Lin [this message]
2022-12-07  6:44     ` Michael Meissner
2022-12-07  7:55       ` Kewen.Lin
2022-12-08 22:04         ` Michael Meissner
2022-12-12 10:20           ` Kewen.Lin
2022-12-13  6:14             ` Michael Meissner
2022-12-13 13:51               ` Segher Boessenkool
2022-12-14  8:45               ` Kewen.Lin
2022-12-13  6:23   ` Michael Meissner
2022-11-02  2:42 ` [PATCH 2/3] Make __float128 use the _Float128 type, " Michael Meissner
2022-11-07 15:43   ` Ping: " Michael Meissner
2022-11-29 17:44   ` Michael Meissner
2022-12-02 18:01   ` Ping #3: " Michael Meissner
2022-12-06 11:27   ` Kewen.Lin
2022-12-14  8:46     ` Kewen.Lin
2022-12-14  9:36       ` Jakub Jelinek
2022-12-14 10:11         ` Kewen.Lin
2022-12-14 10:33           ` Jakub Jelinek
2022-12-15  7:54             ` Kewen.Lin
2022-12-15  7:45           ` Kewen.Lin
2022-12-15 18:28             ` Joseph Myers
2022-12-15 18:49               ` Segher Boessenkool
2022-12-15 18:56                 ` Jakub Jelinek
2022-12-15 20:26                   ` Segher Boessenkool
2022-12-15 17:59         ` Segher Boessenkool
2022-12-16  0:09           ` Michael Meissner
2022-12-16 17:55             ` Segher Boessenkool
2022-12-16 21:53               ` Michael Meissner
2023-01-11 20:24   ` Michael Meissner
2022-11-02  2:44 ` [PATCH 3/3] Update float 128-bit conversions, " Michael Meissner
2022-11-07 15:44   ` Ping: " Michael Meissner
2022-11-29 17:46   ` Ping #3: " Michael Meissner
2022-12-02 18:04   ` Michael Meissner
2022-12-06 14:56 ` Patch [0/3] for PR target/107299 (GCC does not build on PowerPC when long double is IEEE 128-bit) Segher Boessenkool
2022-12-06 15:03   ` Jakub Jelinek
2022-12-13 14:11     ` Segher Boessenkool

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=997752a6-8cd4-abc5-d6e3-2e75eaa37d57@linux.ibm.com \
    --to=linkw@linux.ibm.com \
    --cc=bergner@linux.ibm.com \
    --cc=dje.gcc@gmail.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=meissner@linux.ibm.com \
    --cc=segher@kernel.crashing.org \
    --cc=seurer@gcc.gnu.org \
    --cc=will_schmidt@vnet.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).