public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/meissner/heads/work093)] __float128 and __ibm128 always gets different internal types.
@ 2022-07-06 22:14 Michael Meissner
0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2022-07-06 22:14 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:6cb410e9c36bbbd3e99527f6dbe8054075946841
commit 6cb410e9c36bbbd3e99527f6dbe8054075946841
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Wed Jul 6 18:14:16 2022 -0400
__float128 and __ibm128 always gets different internal types.
2022-07-06 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.
(rs6000_expand_builtin): Remove all of the code that changed
KFmode built-in functions into TFmode, since these functions now
support overloading between KFmode and TFmode.
* config/rs6000/rs600.cc (reg_offset_addressing_ok_p): Allow
IFmode to use offset addresses.
(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_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.md (extendkfif2): New insn.
(trunckfif2): Likewise.
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.
Diff:
---
gcc/config/rs6000/rs6000-builtin.cc | 90 ++------------------
gcc/config/rs6000/rs6000.cc | 122 +++++++++++++++-------------
gcc/config/rs6000/rs6000.md | 18 ++++
gcc/testsuite/gcc.target/powerpc/divkc3-2.c | 2 +-
gcc/testsuite/gcc.target/powerpc/mulkc3-2.c | 2 +-
libgcc/config/rs6000/float128-ifunc.c | 6 ++
libgcc/config/rs6000/quad-float128.h | 5 ++
7 files changed, 103 insertions(+), 142 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
index 2e346d24db6..457e463087f 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -717,18 +717,12 @@ rs6000_init_builtins (void)
format is IBM extended double.
For IEEE 128-bit floating point, always create the type __float128. */
- if (TARGET_LONG_DOUBLE_128 && (!TARGET_IEEEQUAD || TARGET_FLOAT128_TYPE))
+ if (TARGET_LONG_DOUBLE_128 || TARGET_FLOAT128_TYPE)
{
- 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");
}
@@ -737,11 +731,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,
"__float128");
}
@@ -3300,58 +3290,6 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
size_t uns_fcode = (size_t)fcode;
enum insn_code icode = rs6000_builtin_info[uns_fcode].icode;
- /* TODO: The following commentary and code is inherited from the original
- builtin processing code. The commentary is a bit confusing, with the
- intent being that KFmode is always IEEE-128, IFmode is always IBM
- double-double, and TFmode is the current long double. The code is
- confusing in that it converts from KFmode to TFmode pattern names,
- when the other direction is more intuitive. Try to address this. */
-
- /* We have two different modes (KFmode, TFmode) that are the IEEE
- 128-bit floating point type, depending on whether long double is the
- IBM extended double (KFmode) or long double is IEEE 128-bit (TFmode).
- It is simpler if we only define one variant of the built-in function,
- and switch the code when defining it, rather than defining two built-
- ins and using the overload table in rs6000-c.cc to switch between the
- two. If we don't have the proper assembler, don't do this switch
- because CODE_FOR_*kf* and CODE_FOR_*tf* will be CODE_FOR_nothing. */
- if (FLOAT128_IEEE_P (TFmode))
- switch (icode)
- {
- case CODE_FOR_xsxexpqp_kf:
- icode = CODE_FOR_xsxexpqp_tf;
- break;
- case CODE_FOR_xsxsigqp_kf:
- icode = CODE_FOR_xsxsigqp_tf;
- break;
- case CODE_FOR_xststdcnegqp_kf:
- icode = CODE_FOR_xststdcnegqp_tf;
- break;
- case CODE_FOR_xsiexpqp_kf:
- icode = CODE_FOR_xsiexpqp_tf;
- break;
- case CODE_FOR_xsiexpqpf_kf:
- icode = CODE_FOR_xsiexpqpf_tf;
- break;
- case CODE_FOR_xststdcqp_kf:
- icode = CODE_FOR_xststdcqp_tf;
- break;
- case CODE_FOR_xscmpexpqp_eq_kf:
- icode = CODE_FOR_xscmpexpqp_eq_tf;
- break;
- case CODE_FOR_xscmpexpqp_lt_kf:
- icode = CODE_FOR_xscmpexpqp_lt_tf;
- break;
- case CODE_FOR_xscmpexpqp_gt_kf:
- icode = CODE_FOR_xscmpexpqp_gt_tf;
- break;
- case CODE_FOR_xscmpexpqp_unordered_kf:
- icode = CODE_FOR_xscmpexpqp_unordered_tf;
- break;
- default:
- break;
- }
-
/* In case of "#pragma target" changes, we initialize all builtins
but check for actual availability now, during expand time. For
invalid builtins, generate a normal call. */
@@ -3501,22 +3439,6 @@ 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;
/* Position of first argument (0 for void-returning functions, else 1). */
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 3ff16b8ae04..19d1415034f 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -8532,6 +8532,7 @@ reg_offset_addressing_ok_p (machine_mode mode)
case E_TImode:
case E_TFmode:
case E_KFmode:
+ case E_IFmode:
/* AltiVec/VSX vector modes. Only reg+reg addressing was valid until the
ISA 3.0 vector d-form addressing mode was added. While TImode is not
a vector mode, if we want to use the VSX registers to move it around,
@@ -10977,26 +10978,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
{
@@ -11064,32 +11062,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");
@@ -11194,6 +11166,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.
@@ -23816,7 +23828,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_FLOAT128_TYPE || TARGET_LONG_DOUBLE_128) && mode == IFmode)
return true;
else
return default_scalar_mode_supported_p (mode);
@@ -23834,13 +23848,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;
@@ -23874,7 +23884,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 ();
@@ -23898,7 +23908,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 ();
@@ -23916,7 +23926,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
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 1367a2cb779..ec39358ebe8 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -9076,6 +9076,15 @@
DONE;
})
+(define_expand "extendkfif2"
+ [(set (match_operand:IF 0 "gpc_reg_operand")
+ (float_extend:IF (match_operand:KF 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")))]
@@ -9112,6 +9121,15 @@
DONE;
})
+(define_expand "trunckfif2"
+ [(set (match_operand:IF 0 "gpc_reg_operand")
+ (float_truncate:IF (match_operand:KF 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")))]
diff --git a/gcc/testsuite/gcc.target/powerpc/divkc3-2.c b/gcc/testsuite/gcc.target/powerpc/divkc3-2.c
index e34ed40bac2..0cfcea837ed 100644
--- a/gcc/testsuite/gcc.target/powerpc/divkc3-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/divkc3-2.c
@@ -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" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/mulkc3-2.c b/gcc/testsuite/gcc.target/powerpc/mulkc3-2.c
index eee6de9e2a5..78ef1dc00f0 100644
--- a/gcc/testsuite/gcc.target/powerpc/mulkc3-2.c
+++ b/gcc/testsuite/gcc.target/powerpc/mulkc3-2.c
@@ -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" } } */
diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c
index 73cbca2fc9a..30d46bcb233 100644
--- a/libgcc/config/rs6000/float128-ifunc.c
+++ b/libgcc/config/rs6000/float128-ifunc.c
@@ -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")));
diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h
index ae0622c744c..a684d0e1bcf 100644
--- a/libgcc/config/rs6000/quad-float128.h
+++ b/libgcc/config/rs6000/quad-float128.h
@@ -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. */
^ permalink raw reply [flat|nested] 2+ messages in thread
* [gcc(refs/users/meissner/heads/work093)] __float128 and __ibm128 always gets different internal types.
@ 2022-07-06 21:13 Michael Meissner
0 siblings, 0 replies; 2+ messages in thread
From: Michael Meissner @ 2022-07-06 21:13 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:ce07cd65b9672a407f59fbe45107c7e6b373d945
commit ce07cd65b9672a407f59fbe45107c7e6b373d945
Author: Michael Meissner <meissner@linux.ibm.com>
Date: Wed Jul 6 17:13:00 2022 -0400
__float128 and __ibm128 always gets different internal types.
2022-07-06 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.
(rs6000_expand_builtin): Remove all of the code that changed
KFmode built-in functions into TFmode, since these functions now
support overloading between KFmode and TFmode.
* config/rs6000/rs600.cc (reg_offset_addressing_ok_p): Allow
IFmode to use offset addresses.
(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_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.
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.
Diff:
---
gcc/config/rs6000/rs6000-builtin.cc | 90 ++-----------------------
gcc/config/rs6000/rs6000.cc | 122 ++++++++++++++++++----------------
libgcc/config/rs6000/float128-ifunc.c | 6 ++
libgcc/config/rs6000/quad-float128.h | 5 ++
4 files changed, 83 insertions(+), 140 deletions(-)
diff --git a/gcc/config/rs6000/rs6000-builtin.cc b/gcc/config/rs6000/rs6000-builtin.cc
index 2e346d24db6..457e463087f 100644
--- a/gcc/config/rs6000/rs6000-builtin.cc
+++ b/gcc/config/rs6000/rs6000-builtin.cc
@@ -717,18 +717,12 @@ rs6000_init_builtins (void)
format is IBM extended double.
For IEEE 128-bit floating point, always create the type __float128. */
- if (TARGET_LONG_DOUBLE_128 && (!TARGET_IEEEQUAD || TARGET_FLOAT128_TYPE))
+ if (TARGET_LONG_DOUBLE_128 || TARGET_FLOAT128_TYPE)
{
- 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");
}
@@ -737,11 +731,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,
"__float128");
}
@@ -3300,58 +3290,6 @@ rs6000_expand_builtin (tree exp, rtx target, rtx /* subtarget */,
size_t uns_fcode = (size_t)fcode;
enum insn_code icode = rs6000_builtin_info[uns_fcode].icode;
- /* TODO: The following commentary and code is inherited from the original
- builtin processing code. The commentary is a bit confusing, with the
- intent being that KFmode is always IEEE-128, IFmode is always IBM
- double-double, and TFmode is the current long double. The code is
- confusing in that it converts from KFmode to TFmode pattern names,
- when the other direction is more intuitive. Try to address this. */
-
- /* We have two different modes (KFmode, TFmode) that are the IEEE
- 128-bit floating point type, depending on whether long double is the
- IBM extended double (KFmode) or long double is IEEE 128-bit (TFmode).
- It is simpler if we only define one variant of the built-in function,
- and switch the code when defining it, rather than defining two built-
- ins and using the overload table in rs6000-c.cc to switch between the
- two. If we don't have the proper assembler, don't do this switch
- because CODE_FOR_*kf* and CODE_FOR_*tf* will be CODE_FOR_nothing. */
- if (FLOAT128_IEEE_P (TFmode))
- switch (icode)
- {
- case CODE_FOR_xsxexpqp_kf:
- icode = CODE_FOR_xsxexpqp_tf;
- break;
- case CODE_FOR_xsxsigqp_kf:
- icode = CODE_FOR_xsxsigqp_tf;
- break;
- case CODE_FOR_xststdcnegqp_kf:
- icode = CODE_FOR_xststdcnegqp_tf;
- break;
- case CODE_FOR_xsiexpqp_kf:
- icode = CODE_FOR_xsiexpqp_tf;
- break;
- case CODE_FOR_xsiexpqpf_kf:
- icode = CODE_FOR_xsiexpqpf_tf;
- break;
- case CODE_FOR_xststdcqp_kf:
- icode = CODE_FOR_xststdcqp_tf;
- break;
- case CODE_FOR_xscmpexpqp_eq_kf:
- icode = CODE_FOR_xscmpexpqp_eq_tf;
- break;
- case CODE_FOR_xscmpexpqp_lt_kf:
- icode = CODE_FOR_xscmpexpqp_lt_tf;
- break;
- case CODE_FOR_xscmpexpqp_gt_kf:
- icode = CODE_FOR_xscmpexpqp_gt_tf;
- break;
- case CODE_FOR_xscmpexpqp_unordered_kf:
- icode = CODE_FOR_xscmpexpqp_unordered_tf;
- break;
- default:
- break;
- }
-
/* In case of "#pragma target" changes, we initialize all builtins
but check for actual availability now, during expand time. For
invalid builtins, generate a normal call. */
@@ -3501,22 +3439,6 @@ 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;
/* Position of first argument (0 for void-returning functions, else 1). */
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 3ff16b8ae04..19d1415034f 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -8532,6 +8532,7 @@ reg_offset_addressing_ok_p (machine_mode mode)
case E_TImode:
case E_TFmode:
case E_KFmode:
+ case E_IFmode:
/* AltiVec/VSX vector modes. Only reg+reg addressing was valid until the
ISA 3.0 vector d-form addressing mode was added. While TImode is not
a vector mode, if we want to use the VSX registers to move it around,
@@ -10977,26 +10978,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
{
@@ -11064,32 +11062,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");
@@ -11194,6 +11166,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.
@@ -23816,7 +23828,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_FLOAT128_TYPE || TARGET_LONG_DOUBLE_128) && mode == IFmode)
return true;
else
return default_scalar_mode_supported_p (mode);
@@ -23834,13 +23848,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;
@@ -23874,7 +23884,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 ();
@@ -23898,7 +23908,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 ();
@@ -23916,7 +23926,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
diff --git a/libgcc/config/rs6000/float128-ifunc.c b/libgcc/config/rs6000/float128-ifunc.c
index 73cbca2fc9a..30d46bcb233 100644
--- a/libgcc/config/rs6000/float128-ifunc.c
+++ b/libgcc/config/rs6000/float128-ifunc.c
@@ -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")));
diff --git a/libgcc/config/rs6000/quad-float128.h b/libgcc/config/rs6000/quad-float128.h
index ae0622c744c..a684d0e1bcf 100644
--- a/libgcc/config/rs6000/quad-float128.h
+++ b/libgcc/config/rs6000/quad-float128.h
@@ -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. */
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-07-06 22:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-06 22:14 [gcc(refs/users/meissner/heads/work093)] __float128 and __ibm128 always gets different internal types Michael Meissner
-- strict thread matches above, loose matches on Subject: below --
2022-07-06 21:13 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).