public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work105)] Improve PowerPC 128-bit floating point precision support.
@ 2023-01-11  3:20 Michael Meissner
  0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2023-01-11  3:20 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5974cd0030da2ac202b3d0bf796d825e6283471b

commit 5974cd0030da2ac202b3d0bf796d825e6283471b
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Tue Jan 10 22:13:18 2023 -0500

    Improve PowerPC 128-bit floating point precision support.
    
    This patch improves the code for the 3 PowerPC 128-bit floating point types.
    
    There are two main additions with this patch:
    
        1)  Allow the backend to adjust the precision of the 3 types at runtime.
            This allows us to use the same precision for both long double and
            for either __float128 or __ibm128 types.  By having the same precision,
            it makes it easier for the machine independent part of the compiler to
            realize that these modes are talking to the same representation.
    
        2)  Prevent __ibm128 and __float128 from being considered in the automatic
            widening that the compiler does.  This way, you don't have the
            possibility that IFmode (__ibm128) will be widened to TFmode or KFmode,
            even there is hardware to support the IEEE 128-bit operations.
    
    Fortran depends on the current precision values to identify whether the
    current floating point type is IBM extended double or IEEE 128-bit.  While it
    might be nice to fix this in the future so that can just set the precision of
    all 3 modes to be 128, I decided to not make this incompatible change and break
    Fortran.
    
    I also moved changing the TFmode format from ieee to ibm to rs6000-modes.def
    from rs6000.cc.
    
    2022-01-10   Michael Meissner  <meissner@linux.ibm.com>
    
    gcc/
    
            * config/rs6000/rs6000-modes.def (IFmode): Rework to use
            FRACTIONAL_FLOAT_MODE_NO_WIDEN.  Adjust the precision if long double
            uses the same representation.
            (KFmode): Likewise.
            (TFmode): Rework to use FRACTIONAL_FLOAT_MODE_NO_WIDEN.  Adjust the
            format of TFmode based on the -mabi={ibm,ieee}longdouble option.
            * expr.cc (convert_mode_scalar): Don't abort if we are converting
            floating point modes that are the same precision but use different
            encodings.
            * genmodes.cc (struct mode_data): Add support for no widening and
            adjusting precision.
            (blank_mode): Likewise.
            (FRACTIONAL_FLOAT_MODE): Add support for no widening capability.
            (FRACTIONAL_FLOAT_MODE_NO_WIDEN): New macro.
            (make_float_mode): Add support for no widening capability.
            (cmp_modes): Likewise.
            (emit_mode_unit_precision_inline): Add support for adjusting the
            precision.
            (emit_insn_modes_h): Likewise.
            (emit_mode_wider): Add support for no widening capability.
            (emit_mode_unit_precision): Add support for adjusting the precision.
            (emit_mode_adjustments): Likewise.
            * machmode.def (FRACTIONAL_FLOAT_MODE_NO_WIDEN): Document.
            * machmode.h (mode_unit_precision): Add suport for adjusting the
            precision.

Diff:
---
 gcc/config/rs6000/rs6000-modes.def |  41 +++++++-------
 gcc/expr.cc                        |   6 +--
 gcc/genmodes.cc                    | 106 +++++++++++++++++++++++++++++++------
 gcc/machmode.def                   |  13 +++--
 gcc/machmode.h                     |   2 +-
 5 files changed, 123 insertions(+), 45 deletions(-)

diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def
index 8ef910869c5..582f3a6102f 100644
--- a/gcc/config/rs6000/rs6000-modes.def
+++ b/gcc/config/rs6000/rs6000-modes.def
@@ -18,40 +18,41 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
-/* We order the 3 128-bit floating point types so that IFmode (IBM 128-bit
-   floating point) is the 128-bit floating point type with the highest
-   precision (128 bits).  This so that machine independent parts of the
-   compiler do not try to widen IFmode to TFmode on ISA 3.0 (power9) that has
-   hardware support for IEEE 128-bit.  We set TFmode (long double mode) in
-   between, and KFmode (explicit __float128) below it.
-
-   Previously, IFmode and KFmode were defined to be fractional modes and TFmode
-   was the standard mode.  Since IFmode does not define the normal arithmetic
-   insns (other than neg/abs), on a ISA 3.0 system, the machine independent
-   parts of the compiler would see that TFmode has the necessary hardware
-   support, and widen the operation from IFmode to TFmode.  However, IEEE
-   128-bit is not strictly a super-set of IBM extended double and the
-   conversion to/from IEEE 128-bit was a function call.
-
-   We now make IFmode the highest fractional mode, which means its values are
-   not considered for widening.  Since we don't define insns for IFmode, the
-   IEEE 128-bit modes would not widen to IFmode.  */
+/* The 3 128-bit floating point modes (IFmode, KFmode, and TFmode) have unique
+   precisions.  We reset either IFmode or KFmode precision to that of TFmode if
+   those modes match.  We also prevent both IFmode and KFmode from being
+   considered when the compiler tries to widen the types, and we only let the
+   compiler widen SF/DFmode to TFmode.  */
 
 #ifndef RS6000_MODES_H
 #include "config/rs6000/rs6000-modes.h"
 #endif
 
 /* IBM 128-bit floating point.  */
-FRACTIONAL_FLOAT_MODE (IF, FLOAT_PRECISION_IFmode, 16, ibm_extended_format);
+FRACTIONAL_FLOAT_MODE_NO_WIDEN (IF, FLOAT_PRECISION_IFmode, 16,
+				ibm_extended_format);
+
+ADJUST_PRECISION (IF, (FLOAT128_IBM_P (TFmode)
+		       ? FLOAT_PRECISION_TFmode
+		       : FLOAT_PRECISION_IFmode));
 
 /* Explicit IEEE 128-bit floating point.  */
-FRACTIONAL_FLOAT_MODE (KF, FLOAT_PRECISION_KFmode, 16, ieee_quad_format);
+FRACTIONAL_FLOAT_MODE_NO_WIDEN (KF, FLOAT_PRECISION_KFmode, 16,
+				ieee_quad_format);
+
+ADJUST_PRECISION (KF, (FLOAT128_IEEE_P (TFmode)
+		       ? FLOAT_PRECISION_TFmode
+		       : FLOAT_PRECISION_KFmode));
 
 /* 128-bit floating point, either IBM 128-bit or IEEE 128-bit.  This is
    adjusted in rs6000_option_override_internal to be the appropriate floating
    point type.  */
 FRACTIONAL_FLOAT_MODE (TF, FLOAT_PRECISION_TFmode, 16, ieee_quad_format);
 
+ADJUST_FLOAT_FORMAT (TF, (FLOAT128_IBM_P (TFmode)
+			  ? &ibm_extended_format
+			  : &ieee_quad_format));
+
 /* Add any extra modes needed to represent the condition code.
 
    For the RS/6000, we need separate modes when unsigned (logical) comparisons
diff --git a/gcc/expr.cc b/gcc/expr.cc
index 15be1c8db99..c1c1e9729e8 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -345,10 +345,8 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
 		   != GET_MODE_PRECISION (to_mode))
 		  || (DECIMAL_FLOAT_MODE_P (from_mode)
 		      != DECIMAL_FLOAT_MODE_P (to_mode))
-		  || (REAL_MODE_FORMAT (from_mode) == &arm_bfloat_half_format
-		      && REAL_MODE_FORMAT (to_mode) == &ieee_half_format)
-		  || (REAL_MODE_FORMAT (to_mode) == &arm_bfloat_half_format
-		      && REAL_MODE_FORMAT (from_mode) == &ieee_half_format));
+		  || (REAL_MODE_FORMAT (from_mode)
+		      != REAL_MODE_FORMAT (to_mode)));
 
       if (GET_MODE_PRECISION (from_mode) == GET_MODE_PRECISION (to_mode))
 	/* Conversion between decimal float and binary float, same size.  */
diff --git a/gcc/genmodes.cc b/gcc/genmodes.cc
index 2d418f09aab..3f3626a0a8b 100644
--- a/gcc/genmodes.cc
+++ b/gcc/genmodes.cc
@@ -79,6 +79,10 @@ struct mode_data
 				   adjustment */
   unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
   bool boolean;
+  bool normal_widen;		/* Whether the type should be listed in the
+				   mode_wider and mode_2xwider tables.  */
+  bool need_precision_adj;	/* true if this mode needs dynamic precision
+				   adjustment */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
@@ -90,7 +94,7 @@ static const struct mode_data blank_mode = {
   0, -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0, 0,
   "<unknown>", 0, 0, 0, 0, false, false, 0,
-  false
+  false, true, false
 };
 
 static htab_t modes_by_name;
@@ -114,6 +118,7 @@ static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
 static struct mode_adjust *adj_ibit;
 static struct mode_adjust *adj_fbit;
+static struct mode_adjust *adj_precision;
 
 /* Mode class operations.  */
 static enum mode_class
@@ -658,18 +663,22 @@ make_fixed_point_mode (enum mode_class cl,
 
 #define FLOAT_MODE(N, Y, F)             FRACTIONAL_FLOAT_MODE (N, -1U, Y, F)
 #define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
-  make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
+  make_float_mode (#N, B, Y, #F, __FILE__, __LINE__, true)
+#define FRACTIONAL_FLOAT_MODE_NO_WIDEN(N, B, Y, F) \
+  make_float_mode (#N, B, Y, #F, __FILE__, __LINE__, false)
 
 static void
 make_float_mode (const char *name,
 		 unsigned int precision, unsigned int bytesize,
 		 const char *format,
-		 const char *file, unsigned int line)
+		 const char *file, unsigned int line,
+		 bool normal_widen)
 {
   struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
   m->bytesize = bytesize;
   m->precision = precision;
   m->format = format;
+  m->normal_widen = normal_widen;
 }
 
 #define DECIMAL_FLOAT_MODE(N, Y, F)	\
@@ -822,6 +831,7 @@ make_vector_mode (enum mode_class bclass,
 #define ADJUST_FLOAT_FORMAT(M, X)    _ADD_ADJUST (format, M, X, FLOAT, FLOAT)
 #define ADJUST_IBIT(M, X)  _ADD_ADJUST (ibit, M, X, ACCUM, UACCUM)
 #define ADJUST_FBIT(M, X)  _ADD_ADJUST (fbit, M, X, FRACT, UACCUM)
+#define ADJUST_PRECISION(M, X)  _ADD_ADJUST (precision, M, X, FLOAT, FLOAT)
 
 static int bits_per_unit;
 static int max_bitsize_mode_any_int;
@@ -871,7 +881,13 @@ create_modes (void)
    they have the same bytesize; this is the right thing because
    the precision must always be smaller than the bytesize * BITS_PER_UNIT.
    We don't have to do anything special to get this done -- an unset
-   precision shows up as (unsigned int)-1, i.e. UINT_MAX.  */
+   precision shows up as (unsigned int)-1, i.e. UINT_MAX.
+
+   If a mode is listed as no widen, sort it after the modes that are allowed as
+   widening types.  This is for machine dependent floating point types that we
+   don't want to promotion.  In particular on the PowerPC there are 2 different
+   128-bit floating point types (IBM and IEEE) and there are values in each
+   type that can't be represented in the other type.  */
 static int
 cmp_modes (const void *a, const void *b)
 {
@@ -893,6 +909,11 @@ cmp_modes (const void *a, const void *b)
   else if (m->precision < n->precision)
     return -1;
 
+  if (!m->normal_widen && n->normal_widen)
+    return 1;
+  else if (m->normal_widen && !n->normal_widen)
+    return -1;
+
   if (!m->component && !n->component)
     {
       if (m->counter < n->counter)
@@ -1212,7 +1233,8 @@ extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 unsigned short\n\
 mode_unit_precision_inline (machine_mode mode)\n\
 {\n\
-  extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];\n\
+  extern CONST_MODE_PRECISION unsigned short \n\
+    mode_unit_precision[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
   switch (mode)\n\
     {");
@@ -1360,7 +1382,8 @@ enum machine_mode\n{");
 
   /* I can't think of a better idea, can you?  */
   printf ("#define CONST_MODE_NUNITS%s\n", adj_nunits ? "" : " const");
-  printf ("#define CONST_MODE_PRECISION%s\n", adj_nunits ? "" : " const");
+  printf ("#define CONST_MODE_PRECISION%s\n",
+	  adj_precision || adj_nunits ? "" : " const");
   printf ("#define CONST_MODE_SIZE%s\n",
 	  adj_bytesize || adj_nunits ? "" : " const");
   printf ("#define CONST_MODE_UNIT_SIZE%s\n", adj_bytesize ? "" : " const");
@@ -1479,7 +1502,7 @@ emit_mode_precision (void)
   struct mode_data *m;
 
   print_maybe_const_decl ("%spoly_uint16_pod", "mode_precision",
-			  "NUM_MACHINE_MODES", adj_nunits);
+			  "NUM_MACHINE_MODES", adj_precision || adj_nunits);
 
   for_all_modes (c, m)
     if (m->precision != (unsigned int)-1)
@@ -1541,17 +1564,20 @@ emit_mode_wider (void)
     {
       struct mode_data *m2 = 0;
 
-      if (m->cl == MODE_INT
-	  || m->cl == MODE_PARTIAL_INT
-	  || m->cl == MODE_FLOAT
-	  || m->cl == MODE_DECIMAL_FLOAT
-	  || m->cl == MODE_COMPLEX_FLOAT
-	  || m->cl == MODE_FRACT
-	  || m->cl == MODE_UFRACT
-	  || m->cl == MODE_ACCUM
-	  || m->cl == MODE_UACCUM)
+      if (m->normal_widen
+	  && (m->cl == MODE_INT
+	      || m->cl == MODE_PARTIAL_INT
+	      || m->cl == MODE_FLOAT
+	      || m->cl == MODE_DECIMAL_FLOAT
+	      || m->cl == MODE_COMPLEX_FLOAT
+	      || m->cl == MODE_FRACT
+	      || m->cl == MODE_UFRACT
+	      || m->cl == MODE_ACCUM
+	      || m->cl == MODE_UACCUM))
 	for (m2 = m->wider; m2 && m2 != void_mode; m2 = m2->wider)
 	  {
+	    if (!m2->normal_widen)
+	      continue;
 	    if (m2->bytesize == m->bytesize
 		&& m2->precision == m->precision)
 	      continue;
@@ -1576,6 +1602,8 @@ emit_mode_wider (void)
 	   m2 && m2 != void_mode;
 	   m2 = m2->wider)
 	{
+	  if (!m2->normal_widen)
+	    continue;
 	  if (m2->bytesize < 2 * m->bytesize)
 	    continue;
 	  if (m->precision != (unsigned int) -1)
@@ -1699,7 +1727,8 @@ emit_mode_unit_precision (void)
   int c;
   struct mode_data *m;
 
-  print_decl ("unsigned short", "mode_unit_precision", "NUM_MACHINE_MODES");
+  print_maybe_const_decl ("%sunsigned short", "mode_unit_precision",
+			  "NUM_MACHINE_MODES", adj_precision);
 
   for_all_modes (c, m)
     {
@@ -1963,6 +1992,49 @@ emit_mode_adjustments (void)
     printf ("\n  /* %s:%d */\n  REAL_MODE_FORMAT (E_%smode) = %s;\n",
 	    a->file, a->line, a->mode->name, a->adjustment);
 
+
+  /* Precision adjustments propagate too.  */
+  for (a = adj_precision; a; a = a->next)
+    {
+      printf ("\n  /* %s:%d */\n  s = %s;\n",
+	      a->file, a->line, a->adjustment);
+      printf ("  mode_precision[E_%smode] = s;\n", a->mode->name);
+      printf ("  mode_unit_precision[E_%smode] = s;\n", a->mode->name);
+
+      for (m = a->mode->contained; m; m = m->next_cont)
+	{
+	  switch (m->cl)
+	    {
+	    case MODE_COMPLEX_INT:
+	    case MODE_COMPLEX_FLOAT:
+	      printf ("  mode_precision[E_%smode] = 2*s;\n", m->name);
+	      printf ("  mode_unit_precision[E_%smode] = s;\n", m->name);
+	      break;
+
+	    case MODE_VECTOR_BOOL:
+	      /* Changes to BImode should not affect vector booleans.  */
+	      break;
+
+	    case MODE_VECTOR_INT:
+	    case MODE_VECTOR_FLOAT:
+	    case MODE_VECTOR_FRACT:
+	    case MODE_VECTOR_UFRACT:
+	    case MODE_VECTOR_ACCUM:
+	    case MODE_VECTOR_UACCUM:
+	      printf ("  mode_precision[E_%smode] = %d*s;\n",
+		      m->name, m->ncomponents);
+	      printf ("  mode_unit_precision[E_%smode] = s;\n", m->name);
+	      break;
+
+	    default:
+	      internal_error (
+	      "mode %s is neither vector nor complex but contains %s",
+	      m->name, a->mode->name);
+	      /* NOTREACHED */
+	    }
+	}
+    }
+
   puts ("}");
 }
 
diff --git a/gcc/machmode.def b/gcc/machmode.def
index 62e2ba10d45..eb03fd88999 100644
--- a/gcc/machmode.def
+++ b/gcc/machmode.def
@@ -90,6 +90,12 @@ along with GCC; see the file COPYING3.  If not see
 	storage, but with only PRECISION significant bits, using
 	floating point format FORMAT.
 
+     FRACTIONAL_FLOAT_MODE_NO_WIDEN (MODE, PRECISION, BYTESIZE, FORMAT);
+        declares MODE to be of class FLOAT, BYTESIZE bytes wide in
+	storage, but with only PRECISION significant bits, using
+	floating point format FORMAT.  Unlike FRACTIONAL_FLOAT_MODE,
+	MODE is not listed in the mode_wider and mode_2xwider tables.
+
      DECIMAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT);
 	declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes
 	wide.  All of the bits of its representation are significant.
@@ -171,9 +177,10 @@ along with GCC; see the file COPYING3.  If not see
      ADJUST_FLOAT_FORMAT (MODE, EXPR);
      ADJUST_IBIT (MODE, EXPR);
      ADJUST_FBIT (MODE, EXPR);
-	Arrange for the byte size, alignment, floating point format, ibit,
-	or fbit of MODE to be adjustable at run time.  EXPR will be executed
-	once after processing all command line options, and should
+     ADJUST_PRECISION (MODE, EXPR);
+	Arrange for the byte size, alignment, floating point format, ibit, fbit
+	or precision mode of MODE to be adjustable at run time.  EXPR will be
+	executed once after processing all command line options, and should
 	evaluate to the desired byte size, alignment, format, ibit or fbit.
 
 	Unlike a FORMAT argument, if you are adjusting a float format
diff --git a/gcc/machmode.h b/gcc/machmode.h
index f1865c1ef42..e4e0caf9abb 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -27,7 +27,7 @@ extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_inner[NUM_MACHINE_MODES];
 extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
 extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
-extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
+extern CONST_MODE_PRECISION unsigned short mode_unit_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_next[NUM_MACHINE_MODES];
 extern const unsigned char mode_wider[NUM_MACHINE_MODES];
 extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [gcc(refs/users/meissner/heads/work105)] Improve PowerPC 128-bit floating point precision support.
@ 2023-01-11  3:20 Michael Meissner
  0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2023-01-11  3:20 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:8be98ddf50b3252565b73e9e23be11fbea97388e

commit 8be98ddf50b3252565b73e9e23be11fbea97388e
Author: Michael Meissner <meissner@linux.ibm.com>
Date:   Tue Jan 10 22:14:43 2023 -0500

    Improve PowerPC 128-bit floating point precision support.
    
    This patch improves the code for the 3 PowerPC 128-bit floating point types.
    
    There are two main additions with this patch:
    
        1)  Allow the backend to adjust the precision of the 3 types at runtime.
            This allows us to use the same precision for both long double and
            for either __float128 or __ibm128 types.  By having the same precision,
            it makes it easier for the machine independent part of the compiler to
            realize that these modes are talking to the same representation.
    
        2)  Prevent __ibm128 and __float128 from being considered in the automatic
            widening that the compiler does.  This way, you don't have the
            possibility that IFmode (__ibm128) will be widened to TFmode or KFmode,
            even there is hardware to support the IEEE 128-bit operations.
    
    Fortran depends on the current precision values to identify whether the
    current floating point type is IBM extended double or IEEE 128-bit.  While it
    might be nice to fix this in the future so that can just set the precision of
    all 3 modes to be 128, I decided to not make this incompatible change and break
    Fortran.
    
    I also moved changing the TFmode format from ieee to ibm to rs6000-modes.def
    from rs6000.cc.
    
    2022-01-10   Michael Meissner  <meissner@linux.ibm.com>
    
    gcc/
    
            * config/rs6000/rs6000-modes.def (IFmode): Rework to use
            FRACTIONAL_FLOAT_MODE_NO_WIDEN.  Adjust the precision if long double
            uses the same representation.
            (KFmode): Likewise.
            (TFmode): Rework to use FRACTIONAL_FLOAT_MODE_NO_WIDEN.  Adjust the
            format of TFmode based on the -mabi={ibm,ieee}longdouble option.
            * expr.cc (convert_mode_scalar): Don't abort if we are converting
            floating point modes that are the same precision but use different
            encodings.
            * genmodes.cc (struct mode_data): Add support for no widening and
            adjusting precision.
            (blank_mode): Likewise.
            (FRACTIONAL_FLOAT_MODE): Add support for no widening capability.
            (FRACTIONAL_FLOAT_MODE_NO_WIDEN): New macro.
            (make_float_mode): Add support for no widening capability.
            (cmp_modes): Likewise.
            (emit_mode_unit_precision_inline): Add support for adjusting the
            precision.
            (emit_insn_modes_h): Likewise.
            (emit_mode_wider): Add support for no widening capability.
            (emit_mode_unit_precision): Add support for adjusting the precision.
            (emit_mode_adjustments): Likewise.
            * machmode.def (FRACTIONAL_FLOAT_MODE_NO_WIDEN): Document.
            * machmode.h (mode_unit_precision): Add suport for adjusting the
            precision.

Diff:
---
 gcc/config/rs6000/rs6000.cc |   2 +-
 gcc/config/rs6000/rs6000.md | 177 ++++++++++++--------------------------------
 2 files changed, 49 insertions(+), 130 deletions(-)

diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index c508e891413..b64ebeb1a4c 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -11182,7 +11182,7 @@ init_float128_ieee (machine_mode mode)
       if (mode != TFmode && FLOAT128_IBM_P (TFmode))
 	set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2");
 
-      set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2");
+      set_conv_libfunc (sext_optab, IFmode, mode, "__extendkftf2");
       if (mode != TFmode && FLOAT128_IBM_P (TFmode))
 	set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2");
 
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 3cae64a264a..203d0ba6a7f 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -543,12 +543,6 @@
 ; Iterator for 128-bit VSX types for pack/unpack
 (define_mode_iterator FMOVE128_VSX [V1TI KF])
 
-; Iterators for converting to/from TFmode
-(define_mode_iterator IFKF [IF KF])
-
-; Constraints for moving IF/KFmode.
-(define_mode_attr IFKF_reg [(IF "d") (KF "wa")])
-
 ; Whether a floating point move is ok, don't allow SD without hardware FP
 (define_mode_attr fmove_ok [(SF "")
 			    (DF "")
@@ -9161,106 +9155,65 @@
   "xxlor %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
-;; Float128 conversion functions.  These expand to library function calls.
-;; We use expand to convert from IBM double double to IEEE 128-bit
-;; and trunc for the opposite.
-(define_expand "extendiftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand")
-	(float_extend:TF (match_operand:IF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "extendifkf2"
-  [(set (match_operand:KF 0 "gpc_reg_operand")
-	(float_extend:KF (match_operand:IF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "extendtfkf2"
-  [(set (match_operand:KF 0 "gpc_reg_operand")
-	(float_extend:KF (match_operand:TF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "extendtfif2"
-  [(set (match_operand:IF 0 "gpc_reg_operand")
-	(float_extend:IF (match_operand:TF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "trunciftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand")
-	(float_truncate:TF (match_operand:IF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "truncifkf2"
-  [(set (match_operand:KF 0 "gpc_reg_operand")
-	(float_truncate:KF (match_operand:IF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
-{
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
-
-(define_expand "trunckftf2"
-  [(set (match_operand:TF 0 "gpc_reg_operand")
-	(float_truncate:TF (match_operand:KF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
+;; Float128 conversion functions.  We only define the 'conversions' between two
+;; formats that use the same representation.  We call the library function to
+;; convert between IEEE 128-bit and IBM 128-bit.  We can't do these moves by
+;; using a SUBREG before register allocation.  We set up the moves to prefer
+;; the output register being the same as the input register, which would enable
+;; the move to be deleted completely.
+(define_insn_and_split "extendkftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa")
+	(float_extend:TF (match_operand:KF 1 "gpc_reg_operand" "0,wa")))]
+  "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0)
+	(match_dup 2))]
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
+  operands[2] = gen_lowpart (TFmode, operands[1]);
+}
+  [(set_attr "type" "veclogical")])
 
-(define_expand "trunctfif2"
-  [(set (match_operand:IF 0 "gpc_reg_operand")
-	(float_truncate:IF (match_operand:TF 1 "gpc_reg_operand")))]
-  "TARGET_FLOAT128_TYPE"
+(define_insn_and_split "trunctfkf2"
+  [(set (match_operand:KF 0 "gpc_reg_operand" "=wa,wa")
+	(float_truncate:KF (match_operand:TF 1 "gpc_reg_operand" "0,wa")))]
+  "TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (TFmode)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0)
+	(match_dup 2))]
 {
-  rs6000_expand_float128_convert (operands[0], operands[1], false);
-  DONE;
-})
+  operands[2] = gen_lowpart (KFmode, operands[1]);
+}
+  [(set_attr "type" "veclogical")])
 
-(define_insn_and_split "*extend<mode>tf2_internal"
-  [(set (match_operand:TF 0 "gpc_reg_operand" "=<IFKF_reg>")
-	(float_extend:TF
-	 (match_operand:IFKF 1 "gpc_reg_operand" "<IFKF_reg>")))]
-   "TARGET_FLOAT128_TYPE
-    && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (<MODE>mode)"
+(define_insn_and_split "extendtfif2"
+  [(set (match_operand:IF 0 "gpc_reg_operand" "=wa,wa,r,r")
+	(float_extend:IF (match_operand:TF 1 "gpc_reg_operand" "0,wa,0,r")))]
+  "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)"
   "#"
   "&& reload_completed"
-  [(set (match_dup 0) (match_dup 2))]
+  [(set (match_dup 0)
+	(match_dup 2))]
 {
-  operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1]));
-})
+  operands[2] = gen_lowpart (IFmode, operands[1]);
+}
+  [(set_attr "num_insns" "2")
+   (set_attr "length" "8")])
 
-(define_insn_and_split "*extendtf<mode>2_internal"
-  [(set (match_operand:IFKF 0 "gpc_reg_operand" "=<IFKF_reg>")
-	(float_extend:IFKF
-	 (match_operand:TF 1 "gpc_reg_operand" "<IFKF_reg>")))]
-   "TARGET_FLOAT128_TYPE
-    && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (<MODE>mode)"
+(define_insn_and_split "extendiftf2"
+  [(set (match_operand:TF 0 "gpc_reg_operand" "=wa,wa,r,r")
+	(float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "0,wa,0,r")))]
+  "TARGET_HARD_FLOAT && FLOAT128_IBM_P (TFmode)"
   "#"
   "&& reload_completed"
-  [(set (match_dup 0) (match_dup 2))]
+  [(set (match_dup 0)
+	(match_dup 2))]
 {
-  operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
-})
+  operands[2] = gen_lowpart (TFmode, operands[1]);
+}
+  [(set_attr "num_insns" "2")
+   (set_attr "length" "8")])
 
 \f
 ;; Reload helper functions used by rs6000_secondary_reload.  The patterns all
@@ -14983,40 +14936,6 @@
   [(set_attr "type" "vecfloat")
    (set_attr "size" "128")])
 
-;; Conversion between KFmode and TFmode if TFmode is ieee 128-bit floating
-;; point is a simple copy.
-(define_insn_and_split "extendkftf2"
-  [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa")
-	(float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
-  "@
-   #
-   xxlor %x0,%x1,%x1"
-  "&& reload_completed  && REGNO (operands[0]) == REGNO (operands[1])"
-  [(const_int 0)]
-{
-  emit_note (NOTE_INSN_DELETED);
-  DONE;
-}
-  [(set_attr "type" "*,veclogical")
-   (set_attr "length" "0,4")])
-
-(define_insn_and_split "trunctfkf2"
-  [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa")
-	(float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
-  "@
-   #
-   xxlor %x0,%x1,%x1"
-  "&& reload_completed  && REGNO (operands[0]) == REGNO (operands[1])"
-  [(const_int 0)]
-{
-  emit_note (NOTE_INSN_DELETED);
-  DONE;
-}
-  [(set_attr "type" "*,veclogical")
-   (set_attr "length" "0,4")])
-
 (define_insn "trunc<mode>df2_hw"
   [(set (match_operand:DF 0 "altivec_register_operand" "=v")
 	(float_truncate:DF

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-01-11  3:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-11  3:20 [gcc(refs/users/meissner/heads/work105)] Improve PowerPC 128-bit floating point precision support Michael Meissner
2023-01-11  3:20 Michael Meissner

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).