PR target/85456, Fix __builtin_powil for -mabi=ieeelongdouble on PowerPC

Message ID 20180419043345.GA8171@ibm-tiger.the-meissners.org
State New
Headers show
Series
  • PR target/85456, Fix __builtin_powil for -mabi=ieeelongdouble on PowerPC
Related show

Commit Message

Michael Meissner April 19, 2018, 4:33 a.m.
This patch adds __powikf2 to libgcc, and makes GCC use it for __builtin_powil
when long double is IEEE 128-bit (-mabi=ieeelongdouble).

I tested it on a little endian power8 system with a bootstrap compiler.  There
were no regresion failures.  Can I check this into GCC 8?  This does not need
to be checked into GCC 7, since -mabi=ieeelongdouble was not fully supported in
that release.

[libgcc]
2018-04-18  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85456
	* config/rs6000/_powikf2.c: New file.  Entry point for
	__builtin_powil when -mabi=ieeelongdouble is in effect.
	* config/rs6000/float128-ifunc.c (__powikf2_resolve): Add
	__powikf2 support.
	(__powikf2): Likewise.
	* config/rs6000/quad-float128.h (__powikf2_sw): Likewise.
	(__powikf2_hw): Likewise.
	(__powikf2): Likewise.
	* config/rs6000/t-float128 (fp128_ppc_funcs): Likewise.
	* config/rs6000/t-float128-hw (fp128_hw_func): Likewise.
	(_powikf2-hw.c): Likewise.

[gcc]
2018-04-18  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85456
	* config/rs6000/rs6000.c (init_float128_ieee): Add support to call
	__powikf2 when long double is IEEE 128-bit.

[gcc/testsuite]
2018-04-18  Michael Meissner  <meissner@linux.vnet.ibm.com>

	PR target/85456
	* gcc.target/powerpc/pr85456.c: New test.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

Comments

Segher Boessenkool April 20, 2018, 3:52 p.m. | #1
Hi Mike,

On Thu, Apr 19, 2018 at 12:33:45AM -0400, Michael Meissner wrote:
> This patch adds __powikf2 to libgcc, and makes GCC use it for __builtin_powil

> when long double is IEEE 128-bit (-mabi=ieeelongdouble).

> 

> I tested it on a little endian power8 system with a bootstrap compiler.  There

> were no regresion failures.  Can I check this into GCC 8?  This does not need

> to be checked into GCC 7, since -mabi=ieeelongdouble was not fully supported in

> that release.


> [libgcc]

> 2018-04-18  Michael Meissner  <meissner@linux.vnet.ibm.com>

> 

> 	PR target/85456

> 	* config/rs6000/_powikf2.c: New file.  Entry point for

> 	__builtin_powil when -mabi=ieeelongdouble is in effect.

> 	* config/rs6000/float128-ifunc.c (__powikf2_resolve): Add

> 	__powikf2 support.

> 	(__powikf2): Likewise.

> 	* config/rs6000/quad-float128.h (__powikf2_sw): Likewise.

> 	(__powikf2_hw): Likewise.

> 	(__powikf2): Likewise.

> 	* config/rs6000/t-float128 (fp128_ppc_funcs): Likewise.

> 	* config/rs6000/t-float128-hw (fp128_hw_func): Likewise.

> 	(_powikf2-hw.c): Likewise.


This changelog does not make too much sense ("__powikf2: Add __powikf2
support." does not really say what it does, for example).

Does the leading underscore in the filename have any meaning?  The kc
files have one, too, but everything else does not.

> +#if defined(FLOAT128_HW_INSNS) && !defined(__powikf2)

> +#define __powikf2 __powikf2_sw

> +#endif


This could use a comment (it seems the wrong way around if you don't
see how it is built).

> +TFtype

> +__powikf2 (TFtype x, SItype_ppc m)

> +{

> +  unsigned int n = m < 0 ? -m : m;

> +  TFtype y = n % 2 ? x : 1;

> +  while (n >>= 1)

> +    {

> +      x = x * x;

> +      if (n % 2)

> +	y = y * x;

> +    }

> +  return m < 0 ? 1/y : y;

> +}


This work correctly for the most negative integer.  Okay.


Okay for trunk.  Thanks!


Segher
Michael Meissner April 20, 2018, 7:40 p.m. | #2
On Fri, Apr 20, 2018 at 10:52:57AM -0500, Segher Boessenkool wrote:
> Hi Mike,

> 

> On Thu, Apr 19, 2018 at 12:33:45AM -0400, Michael Meissner wrote:

> > This patch adds __powikf2 to libgcc, and makes GCC use it for __builtin_powil

> > when long double is IEEE 128-bit (-mabi=ieeelongdouble).

> > 

> > I tested it on a little endian power8 system with a bootstrap compiler.  There

> > were no regresion failures.  Can I check this into GCC 8?  This does not need

> > to be checked into GCC 7, since -mabi=ieeelongdouble was not fully supported in

> > that release.

> 

> > [libgcc]

> > 2018-04-18  Michael Meissner  <meissner@linux.vnet.ibm.com>

> > 

> > 	PR target/85456

> > 	* config/rs6000/_powikf2.c: New file.  Entry point for

> > 	__builtin_powil when -mabi=ieeelongdouble is in effect.

> > 	* config/rs6000/float128-ifunc.c (__powikf2_resolve): Add

> > 	__powikf2 support.

> > 	(__powikf2): Likewise.

> > 	* config/rs6000/quad-float128.h (__powikf2_sw): Likewise.

> > 	(__powikf2_hw): Likewise.

> > 	(__powikf2): Likewise.

> > 	* config/rs6000/t-float128 (fp128_ppc_funcs): Likewise.

> > 	* config/rs6000/t-float128-hw (fp128_hw_func): Likewise.

> > 	(_powikf2-hw.c): Likewise.

> 

> This changelog does not make too much sense ("__powikf2: Add __powikf2

> support." does not really say what it does, for example).


Ok, I will rewrite it.

> Does the leading underscore in the filename have any meaning?  The kc

> files have one, too, but everything else does not.


It comes from all of the libgcc2.c functions are compiled into _<op><mode>3,
etc.  I kept the same name for consistancy.

> > +#if defined(FLOAT128_HW_INSNS) && !defined(__powikf2)

> > +#define __powikf2 __powikf2_sw

> > +#endif

> 

> This could use a comment (it seems the wrong way around if you don't

> see how it is built).


Ok.

> > +TFtype

> > +__powikf2 (TFtype x, SItype_ppc m)

> > +{

> > +  unsigned int n = m < 0 ? -m : m;

> > +  TFtype y = n % 2 ? x : 1;

> > +  while (n >>= 1)

> > +    {

> > +      x = x * x;

> > +      if (n % 2)

> > +	y = y * x;

> > +    }

> > +  return m < 0 ? 1/y : y;

> > +}

> 

> This work correctly for the most negative integer.  Okay.


It is a copy of the code from libgcc2.c, so it should be correct :-)

For simple code like this and mulkc3/divkc3, it was simpler to just extract the
code from libgcc2, rather than add appropriate KC/KF support to libgcc2.c.

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meissner@linux.vnet.ibm.com, phone: +1 (978) 899-4797

Patch

Index: libgcc/config/rs6000/_powikf2.c
===================================================================
--- libgcc/config/rs6000/_powikf2.c	(revision 0)
+++ libgcc/config/rs6000/_powikf2.c	(revision 0)
@@ -0,0 +1,45 @@ 
+/* Copyright (C) 1989-2018 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* This is a temporary specialization of code from libgcc/libgcc2.c.  */
+
+#include "soft-fp.h"
+#include "quad-float128.h"
+
+#if defined(FLOAT128_HW_INSNS) && !defined(__powikf2)
+#define __powikf2 __powikf2_sw
+#endif
+
+TFtype
+__powikf2 (TFtype x, SItype_ppc m)
+{
+  unsigned int n = m < 0 ? -m : m;
+  TFtype y = n % 2 ? x : 1;
+  while (n >>= 1)
+    {
+      x = x * x;
+      if (n % 2)
+	y = y * x;
+    }
+  return m < 0 ? 1/y : y;
+}
Index: libgcc/config/rs6000/float128-ifunc.c
===================================================================
--- libgcc/config/rs6000/float128-ifunc.c	(revision 259476)
+++ libgcc/config/rs6000/float128-ifunc.c	(working copy)
@@ -84,6 +84,12 @@  __negkf2_resolve (void)
   return SW_OR_HW (__negkf2_sw, __negkf2_hw);
 }
 
+static __typeof__ (__powikf2_sw) *
+__powikf2_resolve (void)
+{
+  return SW_OR_HW (__powikf2_sw, __powikf2_hw);
+}
+
 static __typeof__ (__floatsikf_sw) *
 __floatsikf_resolve (void)
 {
@@ -243,6 +249,9 @@  TFtype __divkf3 (TFtype, TFtype)
 TFtype __negkf2 (TFtype)
   __attribute__ ((__ifunc__ ("__negkf2_resolve")));
 
+TFtype __powikf2 (TFtype, SItype_ppc)
+  __attribute__ ((__ifunc__ ("__powikf2_resolve")));
+
 CMPtype __eqkf2 (TFtype, TFtype)
   __attribute__ ((__ifunc__ ("__eqkf2_resolve")));
 
Index: libgcc/config/rs6000/quad-float128.h
===================================================================
--- libgcc/config/rs6000/quad-float128.h	(revision 259476)
+++ libgcc/config/rs6000/quad-float128.h	(working copy)
@@ -72,6 +72,7 @@  extern TFtype __subkf3_sw (TFtype, TFtyp
 extern TFtype __mulkf3_sw (TFtype, TFtype);
 extern TFtype __divkf3_sw (TFtype, TFtype);
 extern TFtype __negkf2_sw (TFtype);
+extern TFtype __powikf2_sw (TFtype, SItype_ppc);
 extern CMPtype __eqkf2_sw (TFtype, TFtype);
 extern CMPtype __gekf2_sw (TFtype, TFtype);
 extern CMPtype __lekf2_sw (TFtype, TFtype);
@@ -114,6 +115,7 @@  extern TFtype __subkf3_hw (TFtype, TFtyp
 extern TFtype __mulkf3_hw (TFtype, TFtype);
 extern TFtype __divkf3_hw (TFtype, TFtype);
 extern TFtype __negkf2_hw (TFtype);
+extern TFtype __powikf2_hw (TFtype, SItype_ppc);
 extern CMPtype __eqkf2_hw (TFtype, TFtype);
 extern CMPtype __gekf2_hw (TFtype, TFtype);
 extern CMPtype __lekf2_hw (TFtype, TFtype);
@@ -142,6 +144,7 @@  extern TFtype __subkf3 (TFtype, TFtype);
 extern TFtype __mulkf3 (TFtype, TFtype);
 extern TFtype __divkf3 (TFtype, TFtype);
 extern TFtype __negkf2 (TFtype);
+extern TFtype __powikf2 (TFtype, SItype_ppc);
 extern CMPtype __eqkf2 (TFtype, TFtype);
 extern CMPtype __nekf2 (TFtype, TFtype);
 extern CMPtype __gekf2 (TFtype, TFtype);
Index: libgcc/config/rs6000/t-float128
===================================================================
--- libgcc/config/rs6000/t-float128	(revision 259476)
+++ libgcc/config/rs6000/t-float128	(working copy)
@@ -25,7 +25,7 @@  fp128_softfp_obj	= $(fp128_softfp_static
 # New functions for software emulation
 fp128_ppc_funcs		= floattikf floatuntikf fixkfti fixunskfti \
 			  extendkftf2-sw trunctfkf2-sw \
-			  sfp-exceptions _mulkc3 _divkc3
+			  sfp-exceptions _mulkc3 _divkc3 _powikf2
 
 fp128_ppc_src		= $(addprefix $(srcdir)/config/rs6000/,$(addsuffix \
 				.c,$(fp128_ppc_funcs)))
Index: libgcc/config/rs6000/t-float128-hw
===================================================================
--- libgcc/config/rs6000/t-float128-hw	(revision 259476)
+++ libgcc/config/rs6000/t-float128-hw	(working copy)
@@ -6,9 +6,9 @@  FLOAT128_HW_INSNS	= -DFLOAT128_HW_INSNS
 
 # New functions for hardware support
 fp128_hardfp_src	= _mulkc3-hw.c _divkc3-hw.c
-fp128_hw_funcs		= float128-hw _mulkc3-hw _divkc3-hw
+fp128_hw_funcs		= float128-hw _mulkc3-hw _divkc3-hw _powikf2-hw
 fp128_hw_src		= $(srcdir)/config/rs6000/float128-hw.c _mulkc3-hw.c \
-			  _divkc3-hw.c
+			  _divkc3-hw.c _powikf2-hw.c
 fp128_hw_static_obj	= $(addsuffix $(objext),$(fp128_hw_funcs))
 fp128_hw_shared_obj	= $(addsuffix _s$(objext),$(fp128_hw_funcs))
 fp128_hw_obj		= $(fp128_hw_static_obj) $(fp128_hw_shared_obj)
@@ -43,3 +43,7 @@  _mulkc3-hw.c: $(srcdir)/config/rs6000/_m
 _divkc3-hw.c: $(srcdir)/config/rs6000/_divkc3.c
 	(echo "#define __divkc3 __divkc3_hw"; \
 	 cat $(srcdir)/config/rs6000/_divkc3.c) > _divkc3-hw.c
+
+_powikf2-hw.c: $(srcdir)/config/rs6000/_powikf2.c
+	(echo "#define __powikf2 __powikf2_hw"; \
+	 cat $(srcdir)/config/rs6000/_powikf2.c) > _powikf2-hw.c
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 259476)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -18644,6 +18644,7 @@  init_float128_ieee (machine_mode mode)
       set_optab_libfunc (sdiv_optab, mode, "__divkf3");
       set_optab_libfunc (sqrt_optab, mode, "__sqrtkf2");
       set_optab_libfunc (abs_optab, mode, "__abstkf2");
+      set_optab_libfunc (powi_optab, mode, "__powitkf2");
 
       set_optab_libfunc (eq_optab, mode, "__eqkf2");
       set_optab_libfunc (ne_optab, mode, "__nekf2");
Index: gcc/testsuite/gcc.target/powerpc/pr85456.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr85456.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/pr85456.c	(revision 0)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-O2 -mpower8-vector -mabi=ieeelongdouble -Wno-psabi" } */
+
+/* Check that the __builtin_powil generates a call to the correct function
+   when long double uses IEEE 128-bit floating point.  */
+
+long double
+do_powl (long double a, int i)
+{
+  return __builtin_powil (a, i);
+}
+
+/* { dg-final { scan-assembler "bl __powikf2" } } */