rs6000: Fix up __SIZEOF_{FLOAT,IBM}128__ defines [PR99708]

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.
This commit is contained in:
Jakub Jelinek 2022-03-10 10:22:27 +01:00
parent ff060ef08c
commit 6f8abf2b9f
8 changed files with 96 additions and 40 deletions

View 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

View File

@ -138,6 +138,7 @@
; 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
@ -234,13 +235,13 @@
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.

View 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

View 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],

View 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])

View File

@ -0,0 +1,7 @@
/* PR target/99708 */
/* { dg-do compile } */
#ifdef __SIZEOF_FLOAT128__
__float128 f = 1.0;
#endif
long double l = 1.0;

View 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

View File

@ -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;
}