rs6000: Fix up __SIZEOF_{FLOAT,IBM}128__ defines [PR99708]
authorJakub Jelinek <jakub@redhat.com>
Thu, 10 Mar 2022 09:22:27 +0000 (10:22 +0100)
committerJakub Jelinek <jakub@redhat.com>
Thu, 10 Mar 2022 09:22:27 +0000 (10:22 +0100)
As mentioned in the PR, right now on powerpc* __SIZEOF_{FLOAT,IBM}128__
macros are predefined unconditionally, because {ieee,ibm}128_float_type_node
is always non-NULL, doesn't reflect whether __ieee128 or __ibm128 are
actually supported or not.

Based on patch review discussions, the following patch:
1) allows __ibm128 to be used in the sources even when !TARGET_FLOAT128_TYPE,
   as long as long double is double double
2) ensures ibm128_float_type_node is non-NULL only if __ibm128 is supported
3) ensures ieee128_float_type_node is non-NULL only if __ieee128 is supported
   (aka when TARGET_FLOAT128_TYPE)
4) predefines __SIZEOF_IBM128__ only when ibm128_float_type_node != NULL
5) newly predefines __SIZEOF_IEEE128__ if ieee128_float_type_node != NULL
6) predefines __SIZEOF_FLOAT128__ whenever ieee128_float_type_node != NULL
   and __float128 macro is predefined to __ieee128
7) removes ptr_*128_float_type_node which nothing uses
8) in order not to ICE during builtin initialization when
   ibm128_float_type_node == NULL, uses long_double_type_node as fallback
   for the __builtin_{,un}pack_ibm128 builtins
9) errors when those builtins are called used when
   ibm128_float_type_node == NULL (during their expansion)
10) moves the {,un}packif -> {,un}packtf remapping for these builtins in
    expansion earlier, so that we don't ICE on them if not -mabi=ieeelongdouble

2022-03-10  Jakub Jelinek  <jakub@redhat.com>

PR target/99708
* config/rs6000/rs6000.h (enum rs6000_builtin_type_index): Remove
RS6000_BTI_ptr_ieee128_float and RS6000_BTI_ptr_ibm128_float.
(ptr_ieee128_float_type_node, ptr_ibm128_float_type_node): Remove.
* config/rs6000/rs6000-builtin.cc (rs6000_type_string): Return
"**NULL**" if type_node is NULL first.  Handle
ieee128_float_type_node.
(rs6000_init_builtins): Don't initialize ptr_ieee128_float_type_node
and ptr_ibm128_float_type_node.  Set ibm128_float_type_node and
ieee128_float_type_node to NULL rather than long_double_type_node if
they aren't supported.  Do support __ibm128 even if
!TARGET_FLOAT128_TYPE when long double is double double.
(rs6000_expand_builtin): Error if bif_is_ibm128 and
!ibm128_float_type_node.  Remap RS6000_BIF_{,UN}PACK_IF to
RS6000_BIF_{,UN}PACK_TF much earlier and only use bif_is_ibm128 check
for it.
* config/rs6000/rs6000-c.cc (rs6000_target_modify_macros): Define
__SIZEOF_FLOAT128__ here and only iff __float128 macro is defined.
(rs6000_cpu_cpp_builtins): Don't define __SIZEOF_FLOAT128__ here.
Define __SIZEOF_IBM128__=16 if ieee128_float_type_node is non-NULL.
Formatting fix.
* config/rs6000/rs6000-gen-builtins.cc: Document ibm128 attribute.
(struct attrinfo): Add isibm128 member.
(TYPE_MAP_SIZE): Remove.
(type_map): Use [] instead of [TYPE_MAP_SIZE].  For "if" use
ibm128_float_type_node only if it is non-NULL, otherwise fall back
to long_double_type_node.  Remove "pif" entry.
(parse_bif_attrs): Handle ibm128 attribute and print it for debugging.
(write_decls): Output bif_ibm128_bit and bif_is_ibm128.
(write_type_node): Use sizeof type_map / sizeof type_map[0]
instead of TYPE_MAP_SIZE.
(write_bif_static_init): Handle isibm128.
* config/rs6000/rs6000-builtins.def: Document ibm128 attribute.
(__builtin_pack_ibm128, __builtin_unpack_ibm128): Add ibm128
attribute.

* gcc.dg/pr99708.c: New test.
* gcc.target/powerpc/pr99708-2.c: New test.
* gcc.target/powerpc/convert-fp-128.c (mode_kf): Define only if
__FLOAT128_TYPE__ is defined.

gcc/config/rs6000/rs6000-builtin.cc
gcc/config/rs6000/rs6000-builtins.def
gcc/config/rs6000/rs6000-c.cc
gcc/config/rs6000/rs6000-gen-builtins.cc
gcc/config/rs6000/rs6000.h
gcc/testsuite/gcc.dg/pr99708.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/convert-fp-128.c
gcc/testsuite/gcc.target/powerpc/pr99708-2.c [new file with mode: 0644]

index 5d34c1b..e925ba9 100644 (file)
@@ -402,7 +402,9 @@ rs6000_vector_type (const char *name, tree elt_type, unsigned num_elts)
 static
 const char *rs6000_type_string (tree type_node)
 {
-  if (type_node == void_type_node)
+  if (type_node == NULL_TREE)
+    return "**NULL**";
+  else if (type_node == void_type_node)
     return "void";
   else if (type_node == long_integer_type_node)
     return "long";
@@ -432,6 +434,8 @@ const char *rs6000_type_string (tree type_node)
     return "ss";
   else if (type_node == ibm128_float_type_node)
     return "__ibm128";
+  else if (type_node == ieee128_float_type_node)
+    return "__ieee128";
   else if (type_node == opaque_V4SI_type_node)
     return "opaque";
   else if (POINTER_TYPE_P (type_node))
@@ -709,9 +713,9 @@ 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_FLOAT128_TYPE)
+  if (TARGET_LONG_DOUBLE_128 && (!TARGET_IEEEQUAD || TARGET_FLOAT128_TYPE))
     {
-      if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
+      if (!TARGET_IEEEQUAD)
        ibm128_float_type_node = long_double_type_node;
       else
        {
@@ -721,22 +725,24 @@ rs6000_init_builtins (void)
          layout_type (ibm128_float_type_node);
        }
       t = build_qualified_type (ibm128_float_type_node, TYPE_QUAL_CONST);
-      ptr_ibm128_float_type_node = build_pointer_type (t);
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
                                              "__ibm128");
+    }
+  else
+    ibm128_float_type_node = NULL_TREE;
 
+  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);
-      ptr_ieee128_float_type_node = build_pointer_type (t);
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
                                              "__ieee128");
     }
-
   else
-    ieee128_float_type_node = ibm128_float_type_node = long_double_type_node;
+    ieee128_float_type_node = NULL_TREE;
 
   /* Vector pair and vector quad support.  */
   vector_pair_type_node = make_node (OPAQUE_TYPE);
@@ -3418,6 +3424,13 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
       return const0_rtx;
     }
 
+  if (bif_is_ibm128 (*bifaddr) && !ibm128_float_type_node)
+    {
+      error ("%qs requires %<__ibm128%> type support",
+            bifaddr->bifname);
+      return const0_rtx;
+    }
+
   if (bif_is_cpu (*bifaddr))
     return cpu_expand_builtin (fcode, exp, target);
 
@@ -3498,6 +3511,21 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
        gcc_unreachable ();
     }
 
+  if (bif_is_ibm128 (*bifaddr) && TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
+    {
+      if (fcode == RS6000_BIF_PACK_IF)
+       {
+         icode = CODE_FOR_packtf;
+         fcode = RS6000_BIF_PACK_TF;
+         uns_fcode = (size_t) fcode;
+       }
+      else if (fcode == RS6000_BIF_UNPACK_IF)
+       {
+         icode = CODE_FOR_unpacktf;
+         fcode = RS6000_BIF_UNPACK_TF;
+         uns_fcode = (size_t) fcode;
+       }
+    }
 
   /* TRUE iff the built-in function returns void.  */
   bool void_func = TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
@@ -3642,23 +3670,6 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
   if (bif_is_mma (*bifaddr))
     return mma_expand_builtin (exp, target, icode, fcode);
 
-  if (fcode == RS6000_BIF_PACK_IF
-      && TARGET_LONG_DOUBLE_128
-      && !TARGET_IEEEQUAD)
-    {
-      icode = CODE_FOR_packtf;
-      fcode = RS6000_BIF_PACK_TF;
-      uns_fcode = (size_t) fcode;
-    }
-  else if (fcode == RS6000_BIF_UNPACK_IF
-          && TARGET_LONG_DOUBLE_128
-          && !TARGET_IEEEQUAD)
-    {
-      icode = CODE_FOR_unpacktf;
-      fcode = RS6000_BIF_UNPACK_TF;
-      uns_fcode = (size_t) fcode;
-    }
-
   if (TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node)
     target = NULL_RTX;
   else if (target == 0
index ae2760c..221bbc7 100644 (file)
 ;   lxvrze   Needs special handling for load-rightmost, zero-extended
 ;   endian   Needs special handling for endianness
 ;   ibmld    Restrict usage to the case when TFmode is IBM-128
+;   ibm128   Restrict usage to the case where __ibm128 is supported or if ibmld
 ;
 ; Each attribute corresponds to extra processing required when
 ; the built-in is expanded.  All such special processing should
     MTFSF rs6000_mtfsf {}
 
   const __ibm128 __builtin_pack_ibm128 (double, double);
-    PACK_IF packif {}
+    PACK_IF packif {ibm128}
 
   void __builtin_set_fpscr_rn (const int[0,3]);
     SET_FPSCR_RN rs6000_set_fpscr_rn {}
 
   const double __builtin_unpack_ibm128 (__ibm128, const int<1>);
-    UNPACK_IF unpackif {}
+    UNPACK_IF unpackif {ibm128}
 
 ; This is redundant with __builtin_unpack_ibm128, as it requires long
 ; double to be __ibm128.  Should probably be deprecated.
index d2e480a..3b62b49 100644 (file)
@@ -584,6 +584,10 @@ rs6000_target_modify_macros (bool define_p, HOST_WIDE_INT flags,
        rs6000_define_or_undefine_macro (true, "__float128=__ieee128");
       else
        rs6000_define_or_undefine_macro (false, "__float128");
+      if (ieee128_float_type_node && define_p)
+       rs6000_define_or_undefine_macro (true, "__SIZEOF_FLOAT128__=16");
+      else
+       rs6000_define_or_undefine_macro (false, "__SIZEOF_FLOAT128__");
     }
   /* OPTION_MASK_FLOAT128_HARDWARE can be turned on if -mcpu=power9 is used or
      via the target attribute/pragma.  */
@@ -623,11 +627,11 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
   if (TARGET_FLOAT128_TYPE)
-      builtin_define ("__FLOAT128_TYPE__");
+    builtin_define ("__FLOAT128_TYPE__");
   if (ibm128_float_type_node)
     builtin_define ("__SIZEOF_IBM128__=16");
   if (ieee128_float_type_node)
-    builtin_define ("__SIZEOF_FLOAT128__=16");
+    builtin_define ("__SIZEOF_IEEE128__=16");
 #ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
   builtin_define ("__BUILTIN_CPU_SUPPORTS__");
 #endif
index 629ead9..0bd7a53 100644 (file)
@@ -93,6 +93,8 @@ along with GCC; see the file COPYING3.  If not see
      lxvrze   Needs special handling for load-rightmost, zero-extended
      endian   Needs special handling for endianness
      ibmld    Restrict usage to the case when TFmode is IBM-128
+     ibm128   Restrict usage to the case where __ibm128 is supported or
+              if ibmld
 
    An example stanza might look like this:
 
@@ -392,6 +394,7 @@ struct attrinfo
   bool islxvrze;
   bool isendian;
   bool isibmld;
+  bool isibm128;
 };
 
 /* Fields associated with a function prototype (bif or overload).  */
@@ -492,8 +495,7 @@ struct typemap
    maps tokens from a fntype string to a tree type.  For example,
    in "si_ftype_hi" we would map "si" to "intSI_type_node" and
    map "hi" to "intHI_type_node".  */
-#define TYPE_MAP_SIZE 86
-static typemap type_map[TYPE_MAP_SIZE] =
+static typemap type_map[] =
   {
     { "bi",            "bool_int" },
     { "bv16qi",                "bool_V16QI" },
@@ -506,7 +508,9 @@ static typemap type_map[TYPE_MAP_SIZE] =
     { "df",            "double" },
     { "di",            "long_long_integer" },
     { "hi",            "intHI" },
-    { "if",            "ibm128_float" },
+    { "if",            "ibm128_float_type_node "
+                       "? ibm128_float_type_node "
+                       ": long_double" },
     { "ld",            "long_double" },
     { "lg",            "long_integer" },
     { "pbv16qi",       "ptr_bool_V16QI" },
@@ -519,7 +523,6 @@ static typemap type_map[TYPE_MAP_SIZE] =
     { "pdf",           "ptr_double" },
     { "pdi",           "ptr_long_long_integer" },
     { "phi",           "ptr_intHI" },
-    { "pif",           "ptr_ibm128_float" },
     { "pld",           "ptr_long_double" },
     { "plg",           "ptr_long_integer" },
     { "pqi",           "ptr_intQI" },
@@ -1439,6 +1442,8 @@ parse_bif_attrs (attrinfo *attrptr)
          attrptr->isendian = 1;
        else if (!strcmp (attrname, "ibmld"))
          attrptr->isibmld = 1;
+       else if (!strcmp (attrname, "ibm128"))
+         attrptr->isibm128 = 1;
        else
          {
            diag (oldpos, "unknown attribute.\n");
@@ -1472,14 +1477,15 @@ parse_bif_attrs (attrinfo *attrptr)
        "ldvec = %d, stvec = %d, reve = %d, pred = %d, htm = %d, "
        "htmspr = %d, htmcr = %d, mma = %d, quad = %d, pair = %d, "
        "mmaint = %d, no32bit = %d, 32bit = %d, cpu = %d, ldstmask = %d, "
-       "lxvrse = %d, lxvrze = %d, endian = %d, ibmdld= %d.\n",
+       "lxvrse = %d, lxvrze = %d, endian = %d, ibmdld = %d, ibm128 = %d.\n",
        attrptr->isinit, attrptr->isset, attrptr->isextract,
        attrptr->isnosoft, attrptr->isldvec, attrptr->isstvec,
        attrptr->isreve, attrptr->ispred, attrptr->ishtm, attrptr->ishtmspr,
        attrptr->ishtmcr, attrptr->ismma, attrptr->isquad, attrptr->ispair,
        attrptr->ismmaint, attrptr->isno32bit, attrptr->is32bit,
        attrptr->iscpu, attrptr->isldstmask, attrptr->islxvrse,
-       attrptr->islxvrze, attrptr->isendian, attrptr->isibmld);
+       attrptr->islxvrze, attrptr->isendian, attrptr->isibmld,
+       attrptr->isibm128);
 #endif
 
   return PC_OK;
@@ -2294,6 +2300,7 @@ write_decls (void)
   fprintf (header_file, "#define bif_lxvrze_bit\t\t(0x00100000)\n");
   fprintf (header_file, "#define bif_endian_bit\t\t(0x00200000)\n");
   fprintf (header_file, "#define bif_ibmld_bit\t\t(0x00400000)\n");
+  fprintf (header_file, "#define bif_ibm128_bit\t\t(0x00800000)\n");
   fprintf (header_file, "\n");
   fprintf (header_file,
           "#define bif_is_init(x)\t\t((x).bifattrs & bif_init_bit)\n");
@@ -2341,6 +2348,8 @@ write_decls (void)
           "#define bif_is_endian(x)\t((x).bifattrs & bif_endian_bit)\n");
   fprintf (header_file,
           "#define bif_is_ibmld(x)\t((x).bifattrs & bif_ibmld_bit)\n");
+  fprintf (header_file,
+          "#define bif_is_ibm128(x)\t((x).bifattrs & bif_ibm128_bit)\n");
   fprintf (header_file, "\n");
 
   fprintf (header_file,
@@ -2385,8 +2394,10 @@ write_type_node (char *tok, bool indent)
 {
   if (indent)
     fprintf (init_file, "  ");
-  typemap *entry = (typemap *) bsearch (tok, type_map, TYPE_MAP_SIZE,
-                                       sizeof (typemap), typemap_cmp);
+  typemap *entry
+    = (typemap *) bsearch (tok, type_map,
+                          sizeof type_map / sizeof type_map[0],
+                          sizeof (typemap), typemap_cmp);
   if (!entry)
     fatal ("Type map is inconsistent.");
   fprintf (init_file, "%s_type_node", entry->value);
@@ -2535,6 +2546,8 @@ write_bif_static_init (void)
        fprintf (init_file, " | bif_endian_bit");
       if (bifp->attrs.isibmld)
        fprintf (init_file, " | bif_ibmld_bit");
+      if (bifp->attrs.isibm128)
+       fprintf (init_file, " | bif_ibm128_bit");
       fprintf (init_file, ",\n");
       fprintf (init_file, "      /* restr_opnd */\t{%d, %d, %d},\n",
               bifp->proto.restr_opnd[0], bifp->proto.restr_opnd[1],
index 17af314..523256a 100644 (file)
@@ -2444,8 +2444,6 @@ enum rs6000_builtin_type_index
   RS6000_BTI_ptr_long_double,
   RS6000_BTI_ptr_dfloat64,
   RS6000_BTI_ptr_dfloat128,
-  RS6000_BTI_ptr_ieee128_float,
-  RS6000_BTI_ptr_ibm128_float,
   RS6000_BTI_ptr_vector_pair,
   RS6000_BTI_ptr_vector_quad,
   RS6000_BTI_ptr_long_long,
@@ -2541,8 +2539,6 @@ enum rs6000_builtin_type_index
 #define ptr_long_double_type_node       (rs6000_builtin_types[RS6000_BTI_ptr_long_double])
 #define ptr_dfloat64_type_node          (rs6000_builtin_types[RS6000_BTI_ptr_dfloat64])
 #define ptr_dfloat128_type_node                 (rs6000_builtin_types[RS6000_BTI_ptr_dfloat128])
-#define ptr_ieee128_float_type_node     (rs6000_builtin_types[RS6000_BTI_ptr_ieee128_float])
-#define ptr_ibm128_float_type_node      (rs6000_builtin_types[RS6000_BTI_ptr_ibm128_float])
 #define ptr_vector_pair_type_node       (rs6000_builtin_types[RS6000_BTI_ptr_vector_pair])
 #define ptr_vector_quad_type_node       (rs6000_builtin_types[RS6000_BTI_ptr_vector_quad])
 #define ptr_long_long_integer_type_node         (rs6000_builtin_types[RS6000_BTI_ptr_long_long])
diff --git a/gcc/testsuite/gcc.dg/pr99708.c b/gcc/testsuite/gcc.dg/pr99708.c
new file mode 100644 (file)
index 0000000..b1eaf13
--- /dev/null
@@ -0,0 +1,7 @@
+/* PR target/99708 */
+/* { dg-do compile } */
+
+#ifdef __SIZEOF_FLOAT128__
+__float128 f = 1.0;
+#endif
+long double l = 1.0;
index 69f4a02..3e47334 100644 (file)
@@ -7,7 +7,9 @@
 #define mode_sf float
 #define mode_df double
 typedef float __attribute__((mode(IF))) mode_if;
+#ifdef __FLOAT128_TYPE__
 typedef float __attribute__((mode(KF))) mode_kf;
+#endif
 #define mode_sd _Decimal32
 #define mode_dd _Decimal64
 #define mode_td _Decimal128
diff --git a/gcc/testsuite/gcc.target/powerpc/pr99708-2.c b/gcc/testsuite/gcc.target/powerpc/pr99708-2.c
new file mode 100644 (file)
index 0000000..e6f9358
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR target/99708 */
+/* { dg-do compile } */
+
+#ifdef __SIZEOF_IBM128__
+__ibm128 f = 1.0;
+#endif
+#ifdef __SIZEOF_IEEE128__
+__ieee128 g = 1.0;
+#endif
+long double h = 1.0;
+
+void
+foo (void)
+{
+#ifdef __SIZEOF_IBM128__
+  f += 2.0;
+#endif
+#ifdef __SIZEOF_IEEE128__
+  g += 2.0;
+#endif
+  h += 2.0;
+}