]> gcc.gnu.org Git - gcc.git/commitdiff
Make __float128 and __ibm128 use different types from long double.
authorMichael Meissner <meissner@linux.ibm.com>
Thu, 28 Jul 2022 20:57:20 +0000 (16:57 -0400)
committerMichael Meissner <meissner@linux.ibm.com>
Thu, 28 Jul 2022 20:57:20 +0000 (16:57 -0400)
2022-07-28   Michael Meissner  <meissner@linux.ibm.com>

gcc/

* config/rs6000/rs6000-builtin.cc (rs6000_init_builtins): Always
create a new tree node for __ibm128, even if long double uses the IBM
128-bit format.  Always create a new tree node for __float128, even if
long double uses the IEEE 128-bit format.
* config/rs6000/rs600.cc (init_float128_ibm): Remove checks for
hardware floating point for the IBM 128-bit comparisons.
(init_float128_ieee): Do not create __mulkc3 and __divkc3 since
__float128 always creates these functions.
(rs6000_init_libfuncs): Create complex multiply and divide for long
double if long double uses the IEEE 128-bit encoding.
(rs6000_scalar_mode_supported_p): Allow __ibm128 even if we don't
support _Float128.
(rs6000_libgcc_floating_mode_supported_p): Allow KFmode if IEEE
128-bit floating point is supported.  Allow IFmode if either IEEE
128-bit floating point is supported or long double is IBM 128-bit.
(rs6000_floatn_mode): Always return KFmode for IEEE 128-bit.  Do not
return TFmode, even if long double uses the IEEE 128-bit format.
(rs6000_c_mode_for_suffix): The 'q' suffix always uses KFmode, even if
long double uses the IEEE 128-bit encoding.
* config/rs6000/rs6000.h (FLOAT128_IBM_P): Remove checks for
-mhard-float.
(TARGET_IBM128): New macro.

gcc/testsuite/

* gcc.target/powerpc/mulkd3-2.c: Update test.
* gcc.target/powerpc/divkd3-2.c: Likewise.

libgcc/

* config/rs6000/float128-ifunc.c (__multc3_ieee128): Add ifunc
support.
(__divtc3_ieee128): Likewise.
* config/rs6000/quad-float128.h (__multc3_ieee128): Add
        Declaration.
        (__divtc3_ieee128): Likewise.

gcc/config/rs6000/rs6000-builtin.cc
gcc/config/rs6000/rs6000.cc
gcc/config/rs6000/rs6000.h
gcc/testsuite/gcc.target/powerpc/divkc3-2.c
gcc/testsuite/gcc.target/powerpc/mulkc3-2.c
libgcc/config/rs6000/float128-ifunc.c
libgcc/config/rs6000/quad-float128.h

index 67e86bee7815d5f7e5ba83590bb809bd41b44d09..4f5c047539453bd8a878ce31088d1e9bac9d67ee 100644 (file)
@@ -719,18 +719,12 @@ rs6000_init_builtins (void)
      For IEEE 128-bit floating point, always create the type __ieee128.  If the
      user used -mfloat128, rs6000-c.cc will create a define from __float128 to
      __ieee128.  */
-  if (TARGET_LONG_DOUBLE_128 && (!TARGET_IEEEQUAD || TARGET_FLOAT128_TYPE))
+  if (TARGET_IBM128)
     {
-      if (!TARGET_IEEEQUAD)
-       ibm128_float_type_node = long_double_type_node;
-      else
-       {
-         ibm128_float_type_node = make_node (REAL_TYPE);
-         TYPE_PRECISION (ibm128_float_type_node) = 128;
-         SET_TYPE_MODE (ibm128_float_type_node, IFmode);
-         layout_type (ibm128_float_type_node);
-       }
-      t = build_qualified_type (ibm128_float_type_node, TYPE_QUAL_CONST);
+      ibm128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      SET_TYPE_MODE (ibm128_float_type_node, IFmode);
+      layout_type (ibm128_float_type_node);
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
                                              "__ibm128");
     }
@@ -739,11 +733,7 @@ rs6000_init_builtins (void)
 
   if (TARGET_FLOAT128_TYPE)
     {
-      if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
-       ieee128_float_type_node = long_double_type_node;
-      else
-       ieee128_float_type_node = float128_type_node;
-      t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST);
+      ieee128_float_type_node = float128_type_node;
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
                                              "__ieee128");
     }
index ae61505123d6b0c345cabc6f8d88546c48e3f27d..0099c8b95abd2a8ec1ca612ae71f680ec5fe44b7 100644 (file)
@@ -10980,26 +10980,23 @@ init_float128_ibm (machine_mode mode)
       set_optab_libfunc (smul_optab, mode, "__gcc_qmul");
       set_optab_libfunc (sdiv_optab, mode, "__gcc_qdiv");
 
-      if (!TARGET_HARD_FLOAT)
-       {
-         set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
-         set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
-         set_optab_libfunc (ne_optab, mode, "__gcc_qne");
-         set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
-         set_optab_libfunc (ge_optab, mode, "__gcc_qge");
-         set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
-         set_optab_libfunc (le_optab, mode, "__gcc_qle");
-         set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
-
-         set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
-         set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
-         set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
-         set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
-         set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
-         set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
-         set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
-         set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
-       }
+      set_optab_libfunc (neg_optab, mode, "__gcc_qneg");
+      set_optab_libfunc (eq_optab, mode, "__gcc_qeq");
+      set_optab_libfunc (ne_optab, mode, "__gcc_qne");
+      set_optab_libfunc (gt_optab, mode, "__gcc_qgt");
+      set_optab_libfunc (ge_optab, mode, "__gcc_qge");
+      set_optab_libfunc (lt_optab, mode, "__gcc_qlt");
+      set_optab_libfunc (le_optab, mode, "__gcc_qle");
+      set_optab_libfunc (unord_optab, mode, "__gcc_qunord");
+
+      set_conv_libfunc (sext_optab, mode, SFmode, "__gcc_stoq");
+      set_conv_libfunc (sext_optab, mode, DFmode, "__gcc_dtoq");
+      set_conv_libfunc (trunc_optab, SFmode, mode, "__gcc_qtos");
+      set_conv_libfunc (trunc_optab, DFmode, mode, "__gcc_qtod");
+      set_conv_libfunc (sfix_optab, SImode, mode, "__gcc_qtoi");
+      set_conv_libfunc (ufix_optab, SImode, mode, "__gcc_qtou");
+      set_conv_libfunc (sfloat_optab, mode, SImode, "__gcc_itoq");
+      set_conv_libfunc (ufloat_optab, mode, SImode, "__gcc_utoq");
     }
   else
     {
@@ -11067,32 +11064,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");
@@ -11182,10 +11153,11 @@ rs6000_init_libfuncs (void)
 {
   /* __float128 support.  */
   if (TARGET_FLOAT128_TYPE)
-    {
-      init_float128_ibm (IFmode);
-      init_float128_ieee (KFmode);
-    }
+    init_float128_ieee (KFmode);
+
+  /* __ibm128 support.  */
+  if (TARGET_IBM128)
+    init_float128_ibm (IFmode);
 
   /* AIX/Darwin/64-bit Linux quad floating point routines.  */
   if (TARGET_LONG_DOUBLE_128)
@@ -11197,6 +11169,46 @@ rs6000_init_libfuncs (void)
       else
        init_float128_ieee (TFmode);
     }
+
+  /* Set up to call __mulkc3 and __divkc3 when long double uses the IEEE
+     128-bit encoding.  We cannot use the same name (__mulkc3 or __divkc3 for
+     both IEEE long double and for explicit _Float128/__float128) because
+     c_builtin_function will complain if we create two built-in functions with
+     the same name.  Instead we use an alias name for the case when long double
+     uses the IEEE 128-bit encoding.  Libgcc will create a weak alias reference
+     for this name.
+
+     We need to only execute this once.  If we have clone or target attributes,
+     this will be called a second time.  We need to create the built-in
+     function only once.  */
+  static bool complex_muldiv_init_p = false;
+
+  if (TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
+      && !complex_muldiv_init_p)
+    {
+      complex_muldiv_init_p = true;
+
+      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 multiply.  */
+      built_in_function mul_fncode =
+       (built_in_function) (BUILT_IN_COMPLEX_MUL_MIN + TCmode
+                            - MIN_MODE_COMPLEX_FLOAT);
+
+      create_complex_muldiv ("__multc3_ieee128", mul_fncode, fntype);
+
+      /* Create complex divide.  */
+      built_in_function div_fncode =
+       (built_in_function) (BUILT_IN_COMPLEX_DIV_MIN + TCmode
+                            - MIN_MODE_COMPLEX_FLOAT);
+
+      create_complex_muldiv ("__divtc3_ieee128", div_fncode, fntype);
+    }
 }
 
 /* Emit a potentially record-form instruction, setting DST from SRC.
@@ -23819,7 +23831,9 @@ rs6000_scalar_mode_supported_p (scalar_mode mode)
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (TARGET_FLOAT128_TYPE && (mode == KFmode || mode == IFmode))
+  else if (TARGET_FLOAT128_TYPE && mode == KFmode)
+    return true;
+  else if (TARGET_IBM128 && mode == IFmode)
     return true;
   else
     return default_scalar_mode_supported_p (mode);
@@ -23837,13 +23851,9 @@ rs6000_libgcc_floating_mode_supported_p (scalar_float_mode mode)
     case E_TFmode:
       return true;
 
-      /* We only return true for KFmode if IEEE 128-bit types are supported, and
-        if long double does not use the IEEE 128-bit format.  If long double
-        uses the IEEE 128-bit format, it will use TFmode and not KFmode.
-        Because the code will not use KFmode in that case, there will be aborts
-        because it can't find KFmode in the Floatn types.  */
+      /* We only return true for KFmode if IEEE 128-bit types are supported.  */
     case E_KFmode:
-      return TARGET_FLOAT128_TYPE && !TARGET_IEEEQUAD;
+      return TARGET_FLOAT128_TYPE;
 
     default:
       return false;
@@ -23877,7 +23887,7 @@ rs6000_floatn_mode (int n, bool extended)
 
        case 64:
          if (TARGET_FLOAT128_TYPE)
-           return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+           return KFmode;
          else
            return opt_scalar_float_mode ();
 
@@ -23901,7 +23911,7 @@ rs6000_floatn_mode (int n, bool extended)
 
        case 128:
          if (TARGET_FLOAT128_TYPE)
-           return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+           return KFmode;
          else
            return opt_scalar_float_mode ();
 
@@ -23919,7 +23929,7 @@ rs6000_c_mode_for_suffix (char suffix)
   if (TARGET_FLOAT128_TYPE)
     {
       if (suffix == 'q' || suffix == 'Q')
-       return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
+       return KFmode;
 
       /* At the moment, we are not defining a suffix for IBM extended double.
         If/when the default for -mabi=ieeelongdouble is changed, and we want
index 7d04556304a08604e0e9a5f86329bde2757a9d84..7bbd9ab5238968ad2755aa92752fb5825fbb010f 100644 (file)
@@ -334,7 +334,7 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 #define FLOAT128_IBM_P(MODE)                                           \
   ((!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128                         \
     && ((MODE) == TFmode || (MODE) == TCmode))                         \
-   || (TARGET_HARD_FLOAT && ((MODE) == IFmode || (MODE) == ICmode)))
+   || ((MODE) == IFmode || (MODE) == ICmode))
 
 /* Helper macros to say whether a 128-bit floating point type can go in a
    single vector register, or whether it needs paired scalar values.  */
@@ -561,6 +561,12 @@ extern int rs6000_vector_align[];
                                         && TARGET_P8_VECTOR            \
                                         && TARGET_POWERPC64)
 
+/* Whether the __ibm128 keyword is allowed.  Any system that supports _Float128
+   is assumed to be capable of supporting __ibm128.  Similarly if the long
+   double size is 128 bits, we assume __ibm128 is supported.  We don't want to
+   support it on a system without existing 128-bit long doubles.  */
+#define TARGET_IBM128  (TARGET_FLOAT128_TYPE || TARGET_LONG_DOUBLE_128)
+
 /* Inlining allows targets to define the meanings of bits in target_info
    field of ipa_fn_summary by itself, the used bits for rs6000 are listed
    below.  */
index e34ed40bac21953cc3ecf6a098c95007d490b7d0..0cfcea837eda176b0343d6a588dd61d6172ae835 100644 (file)
@@ -14,4 +14,4 @@ divide (cld_t *p, cld_t *q, cld_t *r)
   *p = *q / *r;
 }
 
-/* { dg-final { scan-assembler "bl __divkc3" } } */
+/* { dg-final { scan-assembler "bl __divtc3_ieee128" } } */
index eee6de9e2a54f44310dae4c165a2f38928bdd4f8..78ef1dc00f088069d44ff20bd3454fa4e908b161 100644 (file)
@@ -14,4 +14,4 @@ multiply (cld_t *p, cld_t *q, cld_t *r)
   *p = *q * *r;
 }
 
-/* { dg-final { scan-assembler "bl __mulkc3" } } */
+/* { dg-final { scan-assembler "bl __multc3_ieee128" } } */
index 73cbca2fc9a61a6f2afef4ec1b4e54ebe9e7d662..30d46bcb2330c682a55fbb62011e6c512f5ead17 100644 (file)
@@ -359,3 +359,9 @@ TCtype __mulkc3 (TFtype, TFtype, TFtype, TFtype)
 
 TCtype __divkc3 (TFtype, TFtype, TFtype, TFtype)
   __attribute__ ((__ifunc__ ("__divkc3_resolve")));
+
+TCtype __multc3_ieee128 (TFtype, TFtype, TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__mulkc3_resolve")));
+
+TCtype __divtc3_ieee128 (TFtype, TFtype, TFtype, TFtype)
+  __attribute__ ((__ifunc__ ("__divkc3_resolve")));
index ae0622c744c1ab2f1cec4d0220d238a234278b83..a684d0e1bcf5855244a56f20f37e790d6ae3e0af 100644 (file)
@@ -191,6 +191,11 @@ extern TFtype __trunctfkf2 (IBM128_TYPE);
 extern TCtype __mulkc3 (TFtype, TFtype, TFtype, TFtype);
 extern TCtype __divkc3 (TFtype, TFtype, TFtype, TFtype);
 
+/* Complex long double multiply/divide if long double uses the IEEE 128-bit
+   encoding.  */
+extern TCtype __multc3_ieee128 (TFtype, TFtype, TFtype, TFtype);
+extern TCtype __divtc3_ieee128 (TFtype, TFtype, TFtype, TFtype);
+
 /* Convert IEEE 128-bit floating point to/from string.  We explicitly use
    _Float128 instead of TFmode because _strtokf and _strfromkf must be compiled
    with long double being IBM 128.  */
This page took 0.102211 seconds and 5 git commands to generate.