re PR target/85657 (Make __ibm128 a separate type, even if long double uses the IBM double-double format)
[gcc] 2018-05-21 Michael Meissner <meissner@linux.ibm.com> PR target/85657 * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Do not define __ibm128 as long double. * config/rs6000/rs6000.c (rs6000_init_builtins): Always create __ibm128 as a distinct type. (init_float128_ieee): Fix up conversions between IFmode and IEEE 128-bit types to use the correct functions. (rs6000_expand_float128_convert): Use explicit FLOAT_EXTEND to convert between 128-bit floating point types that have different modes but the same representation, instead of using gen_lowpart to makean alias. * config/rs6000/rs6000.md (IFKF): New iterator for IFmode and KFmode. (IFKF_reg): New attributes to give the register constraints for IFmode and KFmode. (extend<mode>tf2_internal): New insns to mark an explicit conversion between 128-bit floating point types that have a different mode but share the same representation. [gcc/testsuite] 2018-05-21 Michael Meissner <meissner@linux.ibm.com> PR target/85657 * gcc.target/powerpc/pr85657-1.c: New test for converting between __float128, __ibm128, and long double. * gcc.target/powerpc/pr85657-2.c: Likewise. * gcc.target/powerpc/pr85657-3.c: Likewise. * g++.dg/pr85667.C: New test to make sure __ibm128 is implementated as a separate type internally, and is not just an alias for long double. From-SVN: r260489
This commit is contained in:
parent
9c8c733858
commit
75705fa9fd
@ -1,3 +1,24 @@
|
||||
2018-05-21 Michael Meissner <meissner@linux.ibm.com>
|
||||
|
||||
PR target/85657
|
||||
* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Do not
|
||||
define __ibm128 as long double.
|
||||
* config/rs6000/rs6000.c (rs6000_init_builtins): Always create
|
||||
__ibm128 as a distinct type.
|
||||
(init_float128_ieee): Fix up conversions between IFmode and IEEE
|
||||
128-bit types to use the correct functions.
|
||||
(rs6000_expand_float128_convert): Use explicit FLOAT_EXTEND to
|
||||
convert between 128-bit floating point types that have different
|
||||
modes but the same representation, instead of using gen_lowpart to
|
||||
makean alias.
|
||||
* config/rs6000/rs6000.md (IFKF): New iterator for IFmode and
|
||||
KFmode.
|
||||
(IFKF_reg): New attributes to give the register constraints for
|
||||
IFmode and KFmode.
|
||||
(extend<mode>tf2_internal): New insns to mark an explicit
|
||||
conversion between 128-bit floating point types that have a
|
||||
different mode but share the same representation.
|
||||
|
||||
2018-05-21 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
PR tree-optimization/85814
|
||||
|
@ -608,8 +608,6 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
|
||||
builtin_define ("__RSQRTEF__");
|
||||
if (TARGET_FLOAT128_TYPE)
|
||||
builtin_define ("__FLOAT128_TYPE__");
|
||||
if (TARGET_LONG_DOUBLE_128 && FLOAT128_IBM_P (TFmode))
|
||||
builtin_define ("__ibm128=long double");
|
||||
#ifdef TARGET_LIBC_PROVIDES_HWCAP_IN_TCB
|
||||
builtin_define ("__BUILTIN_CPU_SUPPORTS__");
|
||||
#endif
|
||||
|
@ -16347,35 +16347,28 @@ rs6000_init_builtins (void)
|
||||
floating point, we need make sure the type is non-zero or else self-test
|
||||
fails during bootstrap.
|
||||
|
||||
We don't register a built-in type for __ibm128 if the type is the same as
|
||||
long double. Instead we add a #define for __ibm128 in
|
||||
rs6000_cpu_cpp_builtins to long double.
|
||||
Always create __ibm128 as a separate type, even if the current long double
|
||||
format is IBM extended double.
|
||||
|
||||
For IEEE 128-bit floating point, always create the type __ieee128. If the
|
||||
user used -mfloat128, rs6000-c.c will create a define from __float128 to
|
||||
__ieee128. */
|
||||
if (TARGET_LONG_DOUBLE_128 && FLOAT128_IEEE_P (TFmode))
|
||||
if (TARGET_FLOAT128_TYPE)
|
||||
{
|
||||
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");
|
||||
}
|
||||
else
|
||||
ibm128_float_type_node = long_double_type_node;
|
||||
|
||||
if (TARGET_FLOAT128_TYPE)
|
||||
{
|
||||
ieee128_float_type_node = float128_type_node;
|
||||
lang_hooks.types.register_builtin_type (ieee128_float_type_node,
|
||||
"__ieee128");
|
||||
}
|
||||
|
||||
else
|
||||
ieee128_float_type_node = long_double_type_node;
|
||||
ieee128_float_type_node = ibm128_float_type_node = long_double_type_node;
|
||||
|
||||
/* Initialize the modes for builtin_function_type, mapping a machine mode to
|
||||
tree type node. */
|
||||
@ -17865,13 +17858,13 @@ init_float128_ieee (machine_mode mode)
|
||||
set_conv_libfunc (trunc_optab, SFmode, mode, "__trunckfsf2");
|
||||
set_conv_libfunc (trunc_optab, DFmode, mode, "__trunckfdf2");
|
||||
|
||||
set_conv_libfunc (sext_optab, mode, IFmode, "__extendtfkf2");
|
||||
set_conv_libfunc (sext_optab, mode, IFmode, "__trunctfkf2");
|
||||
if (mode != TFmode && FLOAT128_IBM_P (TFmode))
|
||||
set_conv_libfunc (sext_optab, mode, TFmode, "__extendtfkf2");
|
||||
set_conv_libfunc (sext_optab, mode, TFmode, "__trunctfkf2");
|
||||
|
||||
set_conv_libfunc (trunc_optab, IFmode, mode, "__trunckftf2");
|
||||
set_conv_libfunc (trunc_optab, IFmode, mode, "__extendkftf2");
|
||||
if (mode != TFmode && FLOAT128_IBM_P (TFmode))
|
||||
set_conv_libfunc (trunc_optab, TFmode, mode, "__trunckftf2");
|
||||
set_conv_libfunc (trunc_optab, TFmode, mode, "__extendkftf2");
|
||||
|
||||
set_conv_libfunc (sext_optab, mode, SDmode, "__dpd_extendsdkf2");
|
||||
set_conv_libfunc (sext_optab, mode, DDmode, "__dpd_extendddkf2");
|
||||
@ -21700,9 +21693,9 @@ rs6000_expand_float128_convert (rtx dest, rtx src, bool unsigned_p)
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
/* Handle conversion between TFmode/KFmode. */
|
||||
/* Handle conversion between TFmode/KFmode/IFmode. */
|
||||
if (do_move)
|
||||
emit_move_insn (dest, gen_lowpart (dest_mode, src));
|
||||
emit_insn (gen_rtx_SET (dest, gen_rtx_FLOAT_EXTEND (dest_mode, src)));
|
||||
|
||||
/* Handle conversion if we have hardware support. */
|
||||
else if (TARGET_FLOAT128_HW && hw_convert)
|
||||
@ -32128,14 +32121,11 @@ rs6000_mangle_type (const_tree type)
|
||||
if (type == ieee128_float_type_node)
|
||||
return "U10__float128";
|
||||
|
||||
if (TARGET_LONG_DOUBLE_128)
|
||||
{
|
||||
if (type == long_double_type_node)
|
||||
return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
|
||||
if (type == ibm128_float_type_node)
|
||||
return "u8__ibm128";
|
||||
|
||||
if (type == ibm128_float_type_node)
|
||||
return "g";
|
||||
}
|
||||
if (TARGET_LONG_DOUBLE_128 && type == long_double_type_node)
|
||||
return (TARGET_IEEEQUAD) ? "U10__float128" : "g";
|
||||
}
|
||||
|
||||
/* Mangle IBM extended float long double as `g' (__float128) on
|
||||
|
@ -422,6 +422,12 @@
|
||||
; 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 "")
|
||||
@ -8188,6 +8194,32 @@
|
||||
DONE;
|
||||
})
|
||||
|
||||
(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)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0) (match_dup 2))]
|
||||
{
|
||||
operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1]));
|
||||
})
|
||||
|
||||
(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)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0) (match_dup 2))]
|
||||
{
|
||||
operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
|
||||
})
|
||||
|
||||
|
||||
;; Reload helper functions used by rs6000_secondary_reload. The patterns all
|
||||
;; must have 3 arguments, and scratch register constraint must be a single
|
||||
|
@ -1,3 +1,14 @@
|
||||
2018-05-21 Michael Meissner <meissner@linux.ibm.com>
|
||||
|
||||
PR target/85657
|
||||
* gcc.target/powerpc/pr85657-1.c: New test for converting between
|
||||
__float128, __ibm128, and long double.
|
||||
* gcc.target/powerpc/pr85657-2.c: Likewise.
|
||||
* gcc.target/powerpc/pr85657-3.c: Likewise.
|
||||
* g++.dg/pr85667.C: New test to make sure __ibm128 is
|
||||
implementated as a separate type internally, and is not just an
|
||||
alias for long double.
|
||||
|
||||
2018-05-21 Richard Sandiford <richard.sandiford@linaro.org>
|
||||
|
||||
PR tree-optimization/85814
|
||||
|
47
gcc/testsuite/g++.dg/pr85657.C
Normal file
47
gcc/testsuite/g++.dg/pr85657.C
Normal file
@ -0,0 +1,47 @@
|
||||
// { dg-do compile { target { powerpc*-*-linux* } } }
|
||||
// { dg-require-effective-target ppc_float128_sw }
|
||||
// { dg-options "-mvsx -mfloat128 -O2 -mabi=ibmlongdouble -Wno-psabi" }
|
||||
|
||||
// PR 85657
|
||||
// Check that __ibm128 and long double are represented as different types, even
|
||||
// if long double is currently using the same representation as __ibm128.
|
||||
|
||||
template <class __T> inline bool
|
||||
iszero (__T __val)
|
||||
{
|
||||
return __val == 0;
|
||||
}
|
||||
|
||||
int
|
||||
use_template (void)
|
||||
{
|
||||
long double ld = 0.0;
|
||||
__ibm128 ibm = 0.0;
|
||||
|
||||
#ifdef _ARCH_PWR7
|
||||
__asm__ (" # %x0, %x1" : "+d" (ld), "+d" (ibm));
|
||||
#endif
|
||||
|
||||
return iszero (ld) + iszero (ibm);
|
||||
}
|
||||
|
||||
class foo {
|
||||
public:
|
||||
foo () {}
|
||||
~foo () {}
|
||||
inline bool iszero (long double ld) { return ld == 0.0; }
|
||||
inline bool iszero (__ibm128 i128) { return i128 == 0.0; }
|
||||
} st;
|
||||
|
||||
int
|
||||
use_class (void)
|
||||
{
|
||||
long double ld = 0.0;
|
||||
__ibm128 ibm = 0.0;
|
||||
|
||||
#ifdef _ARCH_PWR7
|
||||
__asm__ (" # %x0, %x1" : "+d" (ld), "+d" (ibm));
|
||||
#endif
|
||||
|
||||
return st.iszero (ld) + st.iszero (ibm);
|
||||
}
|
74
gcc/testsuite/gcc.target/powerpc/pr85657-1.c
Normal file
74
gcc/testsuite/gcc.target/powerpc/pr85657-1.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* { dg-do compile { target { powerpc*-*-linux* } } } */
|
||||
/* { dg-require-effective-target ppc_float128_sw } */
|
||||
/* { dg-options "-mvsx -mfloat128 -O2 -mabi=ibmlongdouble -Wno-psabi" } */
|
||||
|
||||
// PR 85657 -- make sure conversions work between each of the 128-bit floating
|
||||
// point types.
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ibm128_to_float128 (__ibm128 a)
|
||||
{
|
||||
return (__float128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ldouble_to_float128 (long double a)
|
||||
{
|
||||
return (__float128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
float128_to_ibm128 (__float128 a)
|
||||
{
|
||||
return (__ibm128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
ldouble_to_ibm128 (long double a)
|
||||
{
|
||||
return (__ibm128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
ibm128_to_ldouble (__ibm128 a)
|
||||
{
|
||||
return (long double)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
float128_to_ldouble (__float128 a)
|
||||
{
|
||||
return (long double)a;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
|
||||
volatile __float128 f128 = 1.2Q;
|
||||
volatile __ibm128 i128 = (__ibm128)3.4L;
|
||||
volatile long double ld = 5.6L;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
printf ("f128 (1.2) = %g (ld), %g (ibm128)\n",
|
||||
(double) float128_to_ldouble (f128),
|
||||
(double) float128_to_ibm128 (f128));
|
||||
|
||||
printf ("i128 (3.4) = %g (ld), %g (float128)\n",
|
||||
(double) ibm128_to_ldouble (i128),
|
||||
(double) ibm128_to_float128 (i128));
|
||||
|
||||
printf ("long double (5.6) = %g (ibm128), %g (float128)\n",
|
||||
(double) ldouble_to_ibm128 (ld),
|
||||
(double) ldouble_to_float128 (ld));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
74
gcc/testsuite/gcc.target/powerpc/pr85657-2.c
Normal file
74
gcc/testsuite/gcc.target/powerpc/pr85657-2.c
Normal file
@ -0,0 +1,74 @@
|
||||
/* { dg-do compile { target { powerpc*-*-linux* } } } */
|
||||
/* { dg-require-effective-target ppc_float128_sw } */
|
||||
/* { dg-options "-mvsx -mfloat128 -O2 -mabi=ieeelongdouble -Wno-psabi" } */
|
||||
|
||||
// PR 85657 -- make sure conversions work between each of the 128-bit floating
|
||||
// point types.
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ibm128_to_float128 (__ibm128 a)
|
||||
{
|
||||
return (__float128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ldouble_to_float128 (long double a)
|
||||
{
|
||||
return (__float128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
float128_to_ibm128 (__float128 a)
|
||||
{
|
||||
return (__ibm128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
ldouble_to_ibm128 (long double a)
|
||||
{
|
||||
return (__ibm128)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
ibm128_to_ldouble (__ibm128 a)
|
||||
{
|
||||
return (long double)a;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
float128_to_ldouble (__float128 a)
|
||||
{
|
||||
return (long double)a;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <stdio.h>
|
||||
|
||||
volatile __float128 f128 = 1.2Q;
|
||||
volatile __ibm128 i128 = (__ibm128)3.4L;
|
||||
volatile long double ld = 5.6L;
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
printf ("f128 (1.2) = %g (ld), %g (ibm128)\n",
|
||||
(double) float128_to_ldouble (f128),
|
||||
(double) float128_to_ibm128 (f128));
|
||||
|
||||
printf ("i128 (3.4) = %g (ld), %g (float128)\n",
|
||||
(double) ibm128_to_ldouble (i128),
|
||||
(double) ibm128_to_float128 (i128));
|
||||
|
||||
printf ("long double (5.6) = %g (ibm128), %g (float128)\n",
|
||||
(double) ldouble_to_ibm128 (ld),
|
||||
(double) ldouble_to_float128 (ld));
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
82
gcc/testsuite/gcc.target/powerpc/pr85657-3.c
Normal file
82
gcc/testsuite/gcc.target/powerpc/pr85657-3.c
Normal file
@ -0,0 +1,82 @@
|
||||
/* { dg-do run { target { powerpc*-*-linux* } } } */
|
||||
/* { dg-require-effective-target ppc_float128_sw } */
|
||||
/* { dg-require-effective-target vsx_hw } */
|
||||
/* { dg-options "-mvsx -O2" } */
|
||||
|
||||
/* PR 85657 -- make __ibm128 a full type. */
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ibm128_to_float128 (__ibm128 a)
|
||||
{
|
||||
return (__float128)a + 1.0q;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__float128
|
||||
ldouble_to_float128 (long double a)
|
||||
{
|
||||
return (__float128)a + 1.0q;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
float128_to_ibm128 (__float128 a)
|
||||
{
|
||||
return (__ibm128)a + (__ibm128)1.0;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
__ibm128
|
||||
ldouble_to_ibm128 (long double a)
|
||||
{
|
||||
return (__ibm128)a + (__ibm128)1.0;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
ibm128_to_ldouble (__ibm128 a)
|
||||
{
|
||||
return (long double)a + 1.0L;
|
||||
}
|
||||
|
||||
__attribute__ ((__noinline__))
|
||||
long double
|
||||
float128_to_ldouble (__float128 a)
|
||||
{
|
||||
return (long double)a + 1.0L;
|
||||
}
|
||||
|
||||
volatile __float128 f128 = 1.25Q;
|
||||
volatile __ibm128 i128 = (__ibm128)3.5L;
|
||||
volatile long double ld = 4.75L;
|
||||
|
||||
volatile double f128_p1 = 2.25;
|
||||
volatile double i128_p1 = 4.5;
|
||||
volatile double ld_p1 = 5.75;
|
||||
|
||||
extern void abort (void);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
if (((double) float128_to_ldouble (f128)) != f128_p1)
|
||||
abort ();
|
||||
|
||||
if (((double) float128_to_ibm128 (f128)) != f128_p1)
|
||||
abort ();
|
||||
|
||||
if (((double) ibm128_to_ldouble (i128)) != i128_p1)
|
||||
abort ();
|
||||
|
||||
if (((double) ibm128_to_float128 (i128)) != i128_p1)
|
||||
abort ();
|
||||
|
||||
if (((double) ldouble_to_ibm128 (ld)) != ld_p1)
|
||||
abort ();
|
||||
|
||||
if (((double) ldouble_to_float128 (ld)) != ld_p1)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user