This patch makes __ibm128 use the long double type node if long double uses the IBM extended double representation, and similarly __float128 will use the long double type node if long double uses the IEEE 128-bit representation.
I have fixed the pr85657.C test case to only test templates, and not explicit overloading. With this fix, the compiler no longer raises an internal error if you use explicit overloading of __ibm128 and long double. Instead it generates the expected error: foo01.C:33:15: error: 'bool foo::iszero(long double)' cannot be overloaded with 'bool foo::iszero(long double)' inline bool iszero (__ibm128 i128) { return i128 == 0.0; } ^~~~~~ foo01.C:32:15: note: previous declaration 'bool foo::iszero(long double)' inline bool iszero (long double ld) { return ld == 0.0; } I have checked this patch on a little endian power8 system and there were no regressions. As I mentioned previously, the pr85657.C now passes. [gcc] 2018-06-05 Michael Meissner <meiss...@linux.ibm.com> * config/rs6000/rs6000.c (rs6000_init_builtins): Make __ibm128 use the long double type if long double is IBM extended double. Make __float128 use the long double type if long double is IEEE 128-bit. [gcc/testsuite] 2018-06-05 Michael Meissner <meiss...@linux.ibm.com> PR target/85657 * g++.dg/pr85657.C: Only test whether __ibm128 and long double can be used in templates. Don't check for them in overloaded functions. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 261175) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -16383,14 +16383,21 @@ rs6000_init_builtins (void) __ieee128. */ 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); + if (TARGET_IEEEQUAD || !TARGET_LONG_DOUBLE_128) + { + 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); + } + else + ibm128_float_type_node = long_double_type_node; + lang_hooks.types.register_builtin_type (ibm128_float_type_node, "__ibm128"); - ieee128_float_type_node = float128_type_node; + ieee128_float_type_node + = TARGET_IEEEQUAD ? long_double_type_node : float128_type_node; lang_hooks.types.register_builtin_type (ieee128_float_type_node, "__ieee128"); } Index: gcc/testsuite/g++.dg/pr85657.C =================================================================== --- gcc/testsuite/g++.dg/pr85657.C (revision 261170) +++ gcc/testsuite/g++.dg/pr85657.C (working copy) @@ -3,8 +3,8 @@ // { 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. +// Check that __ibm128 and long double can be used in the same template, +// even if long double uses the IBM extended double representation. template <class __T> inline bool iszero (__T __val) @@ -18,30 +18,7 @@ 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); -}