From 75705fa9fda3122269231260e6d04f23113eab2e Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Mon, 21 May 2018 22:21:40 +0000 Subject: [PATCH] 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 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. (extendtf2_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 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 --- gcc/ChangeLog | 21 +++++++ gcc/config/rs6000/rs6000-c.c | 2 - gcc/config/rs6000/rs6000.c | 38 +++++-------- gcc/config/rs6000/rs6000.md | 32 +++++++++++ gcc/testsuite/ChangeLog | 11 ++++ gcc/testsuite/g++.dg/pr85657.C | 47 ++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr85657-1.c | 74 +++++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr85657-2.c | 74 +++++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr85657-3.c | 82 ++++++++++++++++++++++++++++ 9 files changed, 355 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/pr85657.C create mode 100644 gcc/testsuite/gcc.target/powerpc/pr85657-1.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr85657-2.c create mode 100644 gcc/testsuite/gcc.target/powerpc/pr85657-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index db367f758d0..6aad0d55d6f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2018-05-21 Michael Meissner + + 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. + (extendtf2_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 PR tree-optimization/85814 diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 98a812efbf0..6cf5537d7ca 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -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 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index d62abdff7ee..26d58fc4c28 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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 diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 6d8e5e219a9..68c0f3af410 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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 "*extendtf2_internal" + [(set (match_operand:TF 0 "gpc_reg_operand" "=") + (float_extend:TF + (match_operand:IFKF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 2))] +{ + operands[2] = gen_rtx_REG (TFmode, REGNO (operands[1])); +}) + +(define_insn_and_split "*extendtf2_internal" + [(set (match_operand:IFKF 0 "gpc_reg_operand" "=") + (float_extend:IFKF + (match_operand:TF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128_TYPE + && FLOAT128_IBM_P (TFmode) == FLOAT128_IBM_P (mode)" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 2))] +{ + operands[2] = gen_rtx_REG (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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 10b757272c5..a115f968dc4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2018-05-21 Michael Meissner + + 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 PR tree-optimization/85814 diff --git a/gcc/testsuite/g++.dg/pr85657.C b/gcc/testsuite/g++.dg/pr85657.C new file mode 100644 index 00000000000..6b81bc2284f --- /dev/null +++ b/gcc/testsuite/g++.dg/pr85657.C @@ -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 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); +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr85657-1.c b/gcc/testsuite/gcc.target/powerpc/pr85657-1.c new file mode 100644 index 00000000000..3337d06332d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr85657-1.c @@ -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 + +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 diff --git a/gcc/testsuite/gcc.target/powerpc/pr85657-2.c b/gcc/testsuite/gcc.target/powerpc/pr85657-2.c new file mode 100644 index 00000000000..33113da8f85 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr85657-2.c @@ -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 + +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 diff --git a/gcc/testsuite/gcc.target/powerpc/pr85657-3.c b/gcc/testsuite/gcc.target/powerpc/pr85657-3.c new file mode 100644 index 00000000000..1d2e69d6341 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr85657-3.c @@ -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; +} -- 2.11.4.GIT