This patch makes some changes to the way the PowerPC handles IEEE 128-bit floating point, and I wanted to point out where I would like to change the compiler, but be open to doing it in other ways.
There are 3 changes in this patch, and presumably more work to do beyond this patch. The first change is to enable the C language to use _Float128 keyword (but not __float128) without having to use the -mfloat128 option on power7-power9 systems. My question is in the TR that introduced _Float128, is there any expectation that outside of the built-in functions we already provide, that we need to provide runtime functions? Yes, glibc 2.26 will be coming along shortly, and it should provide most/all of the F128 functions, but distros won't pick this library up for some time. I would like to enable it, but I want to avoid the problem that we have with __float128 in that once the keyword is supported, it is assumed everything is supported. GCC and GLIBC run on different cycles (and different people work on it), and so you typically have to have GCC add support before GLIBC can use it. We've discovered that boost and libstdc++ both assume the full library support exists if the __float128 keyword is used. We will eventually need to tackle both of these libraries, but we need to the full GLIBC support (or libquadmath) to provide this functionality. Part of the reason for wanting to enable _Float128 without library support or an explicit -mfloat128 is the types and built-in functions have to be set up at compiler startup, and it makes the second change simpler. The second change is to allow #pragma GCC target and attribute((target(...))) to enable IEEE 128-bit __float128 on a per module basis (PR 70589). If I don't enable _Float128 unconditionally, I've discovered that I couldn't find a way to allow _Float128 access after compiler startup. In the second change, I changed how we handle __float128 internally. Previously, we would create the keyword __float128 if -mfloat128, and we would create the same type with the undocumented __ieee128 keyword (you need a keyword to enable the type). Now, I always create the __ieee128 keyword, and if -mfloat128 (or pragma/attribute) is enabled, I add a define: #define __float128 __ieee128 It was a lot simpler to do it this way, rather than trying to keep track of whether the real keyword was __float128 or __ieee128, and do the appropriate define or undef. The third change is to add cpu names 'power7f', 'power8f', and 'power9f' that enable the appropriate power<n> architecture but also does a -mfloat128. The motavation here is you cannot use either #pragma GCC target anywhere or the target attribute on the function with a target_clones attribute declaration. The question is do people see the need for -mcpu=power9f? Or should those be dropped? Assuming we are keeping those, is there a name people prefer instead of just using a 'f' suffix. Note, the GCC infrastructure does not allow a hyphen in the name in creating configargs.h for --with-cpu=<xxx>, etc. At the current time, you cannot use --with-cpu=power8f (it fails in configuring libstdc++, which says that GLIBC supports __float128), but as GLIBC 2.26 becomes more refined, hopefully it will work someday. In writing the tests, I discovered two of the float128 tests could have the target requiements/options tweaked, and I included those changes here. I also discovered we had parallel bits for setting up power7, and I used the ISA 2.06 mask in the power7 definition. So comments on how to proceed? [gcc] 2017-07-20 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/70589 * config.gcc (powerpc*-*-*): Add support for -mcpu=power{7,8,9}f that combines -mcpu=power{7,8,9} with -mfloat128. * config/rs6000/rs6000-cpus.def (OTHER_IEEE_SW_MASKS): New mask of the float128 software/hardware options. (OTHER_IEEE_HW_MASKS): Likewise. (power7 cpu): Replace masks with ISA_2_6_MASKS_SERVER. (power7f): New cpu target that combines a particular machine with -mfloat128. (power8f): Likewise. (power9f): Likewise. * config/rs6000/rs6000-tables.opt: Regenerate. * config/rs6000/rs6000-c.c (rs6000_target_modify_macros): Add support for allowing -mfloat128 to be enabled via target pragma or attribute. Always use __ieee128 for the IEEE 128-bit floating point internal type, and if -mfloat128, add a define from __float128 to __ieee128. (rs6000_cpu_cpp_builtins): Likewise. * config/rs6000/rs6000.c (rs6000_init_builtins): Enable _Float128 if -mfloat128-type is enabled (on by default for VSX systems) rather than -mfloat128 (which controls __float128). (rs6000_floatn_mode): Likewise. (rs6000_opt_masks): Allow float128 and float128-hardware target options to be set. * doc/invoke.texi (PowerPC options): Document -mcpu=power{7,8,9}f. [gcc/testsuite] 2017-07-20 Michael Meissner <meiss...@linux.vnet.ibm.com> PR target/70589 * gcc/testsuite/gcc.target/powerpc/float128-3.c: New test. * gcc/testsuite/gcc.target/powerpc/float128-4.c: Likewise. * gcc/testsuite/gcc.target/powerpc/float128-5.c: Likewise. * gcc/testsuite/gcc.target/powerpc/float128-1.c: Fix test to just use -mvsx instead of hardwiring the cpu to power7. Delete the option -static-libgcc, which is not needed. * gcc/testsuite/gcc.target/powerpc/float128-2.c: Likewise. -- Michael Meissner, IBM IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA email: meiss...@linux.vnet.ibm.com, phone: +1 (978) 899-4797
Index: gcc/config.gcc =================================================================== --- gcc/config.gcc (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config.gcc) (revision 250405) +++ gcc/config.gcc (.../gcc/config.gcc) (working copy) @@ -461,7 +461,7 @@ powerpc*-*-*) extra_headers="${extra_headers} ppu_intrinsics.h spu2vmx.h vec_types.h si2vmx.h" extra_headers="${extra_headers} paired.h" case x$with_cpu in - xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500) + xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456789]|xpower6x|xrs64a|xcell|xa2|xe500mc64|xe5500|xe6500|xpower[789]f) cpu_is_64bit=yes ;; esac @@ -4296,7 +4296,7 @@ case "${target}" in eval "with_$which=405" ;; "" | common | native \ - | power[3456789] | power5+ | power6x \ + | power[3456789] | power5+ | power6x | power[789]f \ | powerpc | powerpc64 | powerpc64le \ | rs64 \ | 401 | 403 | 405 | 405fp | 440 | 440fp | 464 | 464fp \ Index: gcc/config/rs6000/rs6000-tables.opt =================================================================== --- gcc/config/rs6000/rs6000-tables.opt (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000) (revision 250405) +++ gcc/config/rs6000/rs6000-tables.opt (.../gcc/config/rs6000) (working copy) @@ -183,14 +183,23 @@ EnumValue Enum(rs6000_cpu_opt_value) String(power9) Value(51) EnumValue -Enum(rs6000_cpu_opt_value) String(powerpc) Value(52) +Enum(rs6000_cpu_opt_value) String(power7f) Value(52) EnumValue -Enum(rs6000_cpu_opt_value) String(powerpc64) Value(53) +Enum(rs6000_cpu_opt_value) String(power8f) Value(53) EnumValue -Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(54) +Enum(rs6000_cpu_opt_value) String(power9f) Value(54) EnumValue -Enum(rs6000_cpu_opt_value) String(rs64) Value(55) +Enum(rs6000_cpu_opt_value) String(powerpc) Value(55) + +EnumValue +Enum(rs6000_cpu_opt_value) String(powerpc64) Value(56) + +EnumValue +Enum(rs6000_cpu_opt_value) String(powerpc64le) Value(57) + +EnumValue +Enum(rs6000_cpu_opt_value) String(rs64) Value(58) Index: gcc/config/rs6000/rs6000-cpus.def =================================================================== --- gcc/config/rs6000/rs6000-cpus.def (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000) (revision 250405) +++ gcc/config/rs6000/rs6000-cpus.def (.../gcc/config/rs6000) (working copy) @@ -73,6 +73,12 @@ | OPTION_MASK_P9_MISC \ | OPTION_MASK_P9_VECTOR) +/* Extra masks to turn on for IEEE 128-bit floating point support. */ +#define OTHER_IEEE_SW_MASKS (OPTION_MASK_FLOAT128_TYPE \ + | OPTION_MASK_FLOAT128_KEYWORD) + +#define OTHER_IEEE_HW_MASKS (OTHER_IEEE_SW_MASKS | OPTION_MASK_FLOAT128_HW) + /* Support for the IEEE 128-bit floating point hardware requires a lot of the VSX instructions that are part of ISA 3.0. */ #define ISA_3_0_MASKS_IEEE (OPTION_MASK_VSX \ @@ -251,13 +257,16 @@ RS6000_CPU ("power6", PROCESSOR_POWER6, RS6000_CPU ("power6x", PROCESSOR_POWER6, MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_MFPGPR | MASK_RECIP_PRECISION) -RS6000_CPU ("power7", PROCESSOR_POWER7, /* Don't add MASK_ISEL by default */ - POWERPC_7400_MASK | MASK_POWERPC64 | MASK_PPC_GPOPT | MASK_MFCRF - | MASK_POPCNTB | MASK_FPRND | MASK_CMPB | MASK_DFP | MASK_POPCNTD - | MASK_VSX | MASK_RECIP_PRECISION | OPTION_MASK_UPPER_REGS_DF - | OPTION_MASK_UPPER_REGS_DI) +RS6000_CPU ("power7", PROCESSOR_POWER7, MASK_POWERPC64 | ISA_2_6_MASKS_SERVER) RS6000_CPU ("power8", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER) RS6000_CPU ("power9", PROCESSOR_POWER9, MASK_POWERPC64 | ISA_3_0_MASKS_SERVER) +/* Variants that enable -mfloat128 automatically. */ +RS6000_CPU ("power7f", PROCESSOR_POWER7, MASK_POWERPC64 \ + | ISA_2_6_MASKS_SERVER | OTHER_IEEE_SW_MASKS) +RS6000_CPU ("power8f", PROCESSOR_POWER8, MASK_POWERPC64 \ + | ISA_2_7_MASKS_SERVER | OTHER_IEEE_SW_MASKS) +RS6000_CPU ("power9f", PROCESSOR_POWER9, MASK_POWERPC64 \ + | ISA_3_0_MASKS_SERVER | OTHER_IEEE_HW_MASKS) RS6000_CPU ("powerpc", PROCESSOR_POWERPC, 0) RS6000_CPU ("powerpc64", PROCESSOR_POWERPC64, MASK_PPC_GFXOPT | MASK_POWERPC64) RS6000_CPU ("powerpc64le", PROCESSOR_POWER8, MASK_POWERPC64 | ISA_2_7_MASKS_SERVER) Index: gcc/config/rs6000/rs6000-c.c =================================================================== --- gcc/config/rs6000/rs6000-c.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000) (revision 250405) +++ gcc/config/rs6000/rs6000-c.c (.../gcc/config/rs6000) (working copy) @@ -609,6 +609,21 @@ rs6000_target_modify_macros (bool define 2. If TARGET_P8_VECTOR is off. */ if ((flags & OPTION_MASK_UPPER_REGS_SF) != 0) rs6000_define_or_undefine_macro (define_p, "__UPPER_REGS_SF__"); + /* OPTION_MASK_FLOAT128 can be turned on via the -mfloat128 option or via the + target attribute/pragma. The -mfloat128-keyword option must be in + effect. */ + if ((flags & OPTION_MASK_FLOAT128_KEYWORD) != 0) + { + rs6000_define_or_undefine_macro (define_p, "__FLOAT128__"); + if (define_p) + rs6000_define_or_undefine_macro (true, "__float128=__ieee128"); + else + rs6000_define_or_undefine_macro (false, "__float128"); + } + /* OPTION_MASK_FLOAT128_HARDWARE can be turned on if -mcpu=power9 is used or + via the target attribute/pragma. */ + if ((flags & OPTION_MASK_FLOAT128_HW) != 0) + rs6000_define_or_undefine_macro (define_p, "__FLOAT128_HARDWARE__"); /* options from the builtin masks. */ /* Note that RS6000_BTM_PAIRED is enabled only if @@ -636,24 +651,14 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfi builtin_define ("__RSQRTE__"); if (TARGET_FRSQRTES) builtin_define ("__RSQRTEF__"); - if (TARGET_FLOAT128_KEYWORD) - builtin_define ("__FLOAT128__"); if (TARGET_FLOAT128_TYPE) builtin_define ("__FLOAT128_TYPE__"); - if (TARGET_FLOAT128_HW) - builtin_define ("__FLOAT128_HARDWARE__"); 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 - /* We needed to create a keyword if -mfloat128-type was used but not -mfloat, - so we used __ieee128. If -mfloat128 was used, create a #define back to - the real keyword in case somebody used it. */ - if (TARGET_FLOAT128_KEYWORD) - builtin_define ("__ieee128=__float128"); - if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM) { /* Define the AltiVec syntactic elements. */ Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/config/rs6000) (revision 250405) +++ gcc/config/rs6000/rs6000.c (.../gcc/config/rs6000) (working copy) @@ -16991,16 +16991,17 @@ rs6000_init_builtins (void) format that uses a pair of doubles, depending on the switches and defaults. - We do not enable the actual __float128 keyword unless the user explicitly - asks for it, because the library support is not yet complete. - If we don't support for either 128-bit IBM double double or IEEE 128-bit 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. */ + rs6000_cpu_cpp_builtins to long 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)) { ibm128_float_type_node = make_node (REAL_TYPE); @@ -17014,24 +17015,10 @@ rs6000_init_builtins (void) else ibm128_float_type_node = long_double_type_node; - if (TARGET_FLOAT128_KEYWORD) + if (TARGET_FLOAT128_TYPE) { ieee128_float_type_node = float128_type_node; lang_hooks.types.register_builtin_type (ieee128_float_type_node, - "__float128"); - } - - else if (TARGET_FLOAT128_TYPE) - { - ieee128_float_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (ibm128_float_type_node) = 128; - SET_TYPE_MODE (ieee128_float_type_node, KFmode); - layout_type (ieee128_float_type_node); - - /* If we are not exporting the __float128/_Float128 keywords, we need a - keyword to get the types created. Use __ieee128 as the dummy - keyword. */ - lang_hooks.types.register_builtin_type (ieee128_float_type_node, "__ieee128"); } @@ -36212,7 +36199,7 @@ rs6000_floatn_mode (int n, bool extended return DFmode; case 64: - if (TARGET_FLOAT128_KEYWORD) + if (TARGET_FLOAT128_TYPE) return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode; else return VOIDmode; @@ -36236,7 +36223,7 @@ rs6000_floatn_mode (int n, bool extended return DFmode; case 128: - if (TARGET_FLOAT128_KEYWORD) + if (TARGET_FLOAT128_TYPE) return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode; else return VOIDmode; @@ -36326,9 +36313,9 @@ static struct rs6000_opt_mask const rs60 { "dlmzb", OPTION_MASK_DLMZB, false, true }, { "efficient-unaligned-vsx", OPTION_MASK_EFFICIENT_UNALIGNED_VSX, false, true }, - { "float128", OPTION_MASK_FLOAT128_KEYWORD, false, false }, + { "float128", OPTION_MASK_FLOAT128_KEYWORD, false, true }, { "float128-type", OPTION_MASK_FLOAT128_TYPE, false, false }, - { "float128-hardware", OPTION_MASK_FLOAT128_HW, false, false }, + { "float128-hardware", OPTION_MASK_FLOAT128_HW, false, true }, { "fprnd", OPTION_MASK_FPRND, false, true }, { "hard-dfp", OPTION_MASK_DFP, false, true }, { "htm", OPTION_MASK_HTM, false, true }, Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/doc) (revision 250405) +++ gcc/doc/invoke.texi (.../gcc/doc) (working copy) @@ -21675,6 +21675,7 @@ Supported values for @var{cpu_type} are @samp{titan}, @samp{power3}, @samp{power4}, @samp{power5}, @samp{power5+}, @samp{power6}, @samp{power6x}, @samp{power7}, @samp{power8}, @samp{power9}, @samp{powerpc}, @samp{powerpc64}, @samp{powerpc64le}, +@samp{power7f}, @samp{power8f}, @samp{power9f} and @samp{rs64}. @option{-mcpu=powerpc}, @option{-mcpu=powerpc64}, and @@ -21687,6 +21688,10 @@ The other options specify a specific pro those options runs best on that processor, and may not run at all on others. +The options @samp{power7f}, @samp{power8f}, and @samp{power9f} set the +processor to power7, power8, or power9, and also enable the +@option{-mfloat128} option. + The @option{-mcpu} options automatically enable or disable the following options: @@ -21961,6 +21966,10 @@ If you use the ISA 3.0 instruction set ( IEEE 128-bit floating point instructions. Otherwise, IEEE 128-bit floating point will be done with software emulation. +If you use @option{-mcpu=power7f} or @option{-mcpu=power8f}, it sets +the @option{-mfloat128} option as well as setting the processor type +to @var{power7} (ISA 2.05) or @var{power8} (ISA 2.06). + @item -mfloat128-hardware @itemx -mno-float128-hardware @opindex mfloat128-hardware @@ -21975,6 +21984,10 @@ If you select ISA 3.0 instructions with not use either @option{-mfloat128} or @option{-mfloat128-hardware}, the IEEE 128-bit floating point support will not be enabled. +If you use @option{-mcpu=power9f}, it sets the @option{-mfloat128} +option as well as setting the processor to @var{power9} (i.e. ISA +3.0). + @item -mfloat-gprs=@var{yes/single/double/no} @itemx -mfloat-gprs @opindex mfloat-gprs Index: gcc/testsuite/gcc.target/powerpc/float128-3.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-3.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-3.c (.../gcc/testsuite/gcc.target/powerpc) (revision 250406) @@ -0,0 +1,150 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target ppc_float128_sw } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7f" } } */ +/* { dg-options "-mcpu=power7f -O2" } */ + +/* This test is a clone of float128-1.c, using -mcpu=power7f. */ + +#ifdef DEBUG +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <inttypes.h> +#endif + +#if !defined(__FLOAT128__) || !defined(_ARCH_PPC) +static __float128 +pass_through (__float128 x) +{ + return x; +} + +__float128 (*no_optimize) (__float128) = pass_through; +#endif + +#ifdef DEBUG +__attribute__((__noinline__)) +static void +print_f128 (__float128 x) +{ + unsigned sign; + unsigned exponent; + uint64_t mantissa1; + uint64_t mantissa2; + uint64_t upper; + uint64_t lower; + +#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__) + struct ieee128 { + uint64_t upper; + uint64_t lower; + }; + +#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__) + struct ieee128 { + uint64_t lower; + uint64_t upper; + }; + +#else +#error "Unknown system" +#endif + + union { + __float128 f128; + struct ieee128 s128; + } u; + + u.f128 = x; + upper = u.s128.upper; + lower = u.s128.lower; + + sign = (unsigned)((upper >> 63) & 1); + exponent = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1)); + mantissa1 = (upper & ((((uint64_t)1) << 48) - 1)); + mantissa2 = lower; + + printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64, + sign ? '-' : '+', + exponent, + mantissa1, + mantissa2); +} +#endif + +__attribute__((__noinline__)) +static void +do_test (__float128 expected, __float128 got, const char *name) +{ + int equal_p = (expected == got); + +#ifdef DEBUG + printf ("Test %s, expected: ", name); + print_f128 (expected); + printf (" %5g, got: ", (double) expected); + print_f128 (got); + printf (" %5g, result %s\n", + (double) got, + (equal_p) ? "equal" : "not equal"); +#endif + + if (!equal_p) + __builtin_abort (); +} + + +int +main (void) +{ + __float128 one = 1.0q; + __float128 two = 2.0q; + __float128 three = 3.0q; + __float128 four = 4.0q; + __float128 five = 5.0q; + __float128 add_result = (1.0q + 2.0q); + __float128 mul_result = ((1.0q + 2.0q) * 3.0q); + __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q); + __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q); + __float128 neg_result = - sub_result; + __float128 add_xresult; + __float128 mul_xresult; + __float128 div_xresult; + __float128 sub_xresult; + __float128 neg_xresult; + +#if defined(__FLOAT128__) && defined(_ARCH_PPC) + __asm__ (" #prevent constant folding, %x0" : "+wa" (one)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (two)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (three)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (four)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (five)); + +#else + one = no_optimize (one); + two = no_optimize (two); + three = no_optimize (three); + four = no_optimize (four); + five = no_optimize (five); +#endif + + add_xresult = (one + two); + do_test (add_result, add_xresult, "add"); + + mul_xresult = add_xresult * three; + do_test (mul_result, mul_xresult, "mul"); + + div_xresult = mul_xresult / four; + do_test (div_result, div_xresult, "div"); + + sub_xresult = div_xresult - five; + do_test (sub_result, sub_xresult, "sub"); + + neg_xresult = - sub_xresult; + do_test (neg_result, neg_xresult, "neg"); + +#ifdef DEBUG + printf ("Passed\n"); +#endif + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-4.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-4.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-4.c (.../gcc/testsuite/gcc.target/powerpc) (revision 250406) @@ -0,0 +1,150 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target ppc_float128_hw } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9f" } } */ +/* { dg-options "-mcpu=power9f -O2" } */ + +/* This test is a clone of float128-1.c, using -mcpu=power9f. */ + +#ifdef DEBUG +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <inttypes.h> +#endif + +#if !defined(__FLOAT128__) || !defined(_ARCH_PPC) +static __float128 +pass_through (__float128 x) +{ + return x; +} + +__float128 (*no_optimize) (__float128) = pass_through; +#endif + +#ifdef DEBUG +__attribute__((__noinline__)) +static void +print_f128 (__float128 x) +{ + unsigned sign; + unsigned exponent; + uint64_t mantissa1; + uint64_t mantissa2; + uint64_t upper; + uint64_t lower; + +#if defined(_ARCH_PPC) && defined(__BIG_ENDIAN__) + struct ieee128 { + uint64_t upper; + uint64_t lower; + }; + +#elif (defined(_ARCH_PPC) && defined(__LITTLE_ENDIAN__)) || defined(__x86_64__) + struct ieee128 { + uint64_t lower; + uint64_t upper; + }; + +#else +#error "Unknown system" +#endif + + union { + __float128 f128; + struct ieee128 s128; + } u; + + u.f128 = x; + upper = u.s128.upper; + lower = u.s128.lower; + + sign = (unsigned)((upper >> 63) & 1); + exponent = (unsigned)((upper >> 48) & ((((uint64_t)1) << 16) - 1)); + mantissa1 = (upper & ((((uint64_t)1) << 48) - 1)); + mantissa2 = lower; + + printf ("%c 0x%.4x 0x%.12" PRIx64 " 0x%.16" PRIx64, + sign ? '-' : '+', + exponent, + mantissa1, + mantissa2); +} +#endif + +__attribute__((__noinline__)) +static void +do_test (__float128 expected, __float128 got, const char *name) +{ + int equal_p = (expected == got); + +#ifdef DEBUG + printf ("Test %s, expected: ", name); + print_f128 (expected); + printf (" %5g, got: ", (double) expected); + print_f128 (got); + printf (" %5g, result %s\n", + (double) got, + (equal_p) ? "equal" : "not equal"); +#endif + + if (!equal_p) + __builtin_abort (); +} + + +int +main (void) +{ + __float128 one = 1.0q; + __float128 two = 2.0q; + __float128 three = 3.0q; + __float128 four = 4.0q; + __float128 five = 5.0q; + __float128 add_result = (1.0q + 2.0q); + __float128 mul_result = ((1.0q + 2.0q) * 3.0q); + __float128 div_result = (((1.0q + 2.0q) * 3.0q) / 4.0q); + __float128 sub_result = ((((1.0q + 2.0q) * 3.0q) / 4.0q) - 5.0q); + __float128 neg_result = - sub_result; + __float128 add_xresult; + __float128 mul_xresult; + __float128 div_xresult; + __float128 sub_xresult; + __float128 neg_xresult; + +#if defined(__FLOAT128__) && defined(_ARCH_PPC) + __asm__ (" #prevent constant folding, %x0" : "+wa" (one)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (two)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (three)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (four)); + __asm__ (" #prevent constant folding, %x0" : "+wa" (five)); + +#else + one = no_optimize (one); + two = no_optimize (two); + three = no_optimize (three); + four = no_optimize (four); + five = no_optimize (five); +#endif + + add_xresult = (one + two); + do_test (add_result, add_xresult, "add"); + + mul_xresult = add_xresult * three; + do_test (mul_result, mul_xresult, "mul"); + + div_xresult = mul_xresult / four; + do_test (div_result, div_xresult, "div"); + + sub_xresult = div_xresult - five; + do_test (sub_result, sub_xresult, "sub"); + + neg_xresult = - sub_xresult; + do_test (neg_result, neg_xresult, "neg"); + +#ifdef DEBUG + printf ("Passed\n"); +#endif + + return 0; +} Index: gcc/testsuite/gcc.target/powerpc/float128-5.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-5.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 0) +++ gcc/testsuite/gcc.target/powerpc/float128-5.c (.../gcc/testsuite/gcc.target/powerpc) (revision 250406) @@ -0,0 +1,21 @@ +/* { dg-do compile { target { powerpc*-*-linux* } } } */ +/* { dg-require-effective-target powerpc_float128_sw_ok } */ +/* { dg-options "-O2 -mvsx -mno-float128" } */ + +/* Test that we can use #pragma GCC target to enable -mfloat128. */ + +#ifdef __FLOAT128__ +#error "-mno-float128 should disable initially defining __FLOAT128__" +#endif + +#pragma GCC target("float128") + +#ifndef __FLOAT128__ +#error "#pragma GCC target(\"float128\") should enable -mfloat128" +#endif + +__float128 +qadd (__float128 a, __float128 b) +{ + return a+b; +} Index: gcc/testsuite/gcc.target/powerpc/float128-1.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-1.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 250405) +++ gcc/testsuite/gcc.target/powerpc/float128-1.c (.../gcc/testsuite/gcc.target/powerpc) (working copy) @@ -1,6 +1,7 @@ /* { dg-do run { target { powerpc*-*-linux* } } } */ /* { dg-require-effective-target ppc_float128_sw } */ -/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-mvsx -O2 -mfloat128" } */ #ifdef DEBUG #include <stdio.h> Index: gcc/testsuite/gcc.target/powerpc/float128-2.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/float128-2.c (.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk/gcc/testsuite/gcc.target/powerpc) (revision 250405) +++ gcc/testsuite/gcc.target/powerpc/float128-2.c (.../gcc/testsuite/gcc.target/powerpc) (working copy) @@ -1,6 +1,7 @@ /* { dg-do run { target { powerpc*-*-linux* } } } */ /* { dg-require-effective-target ppc_float128_sw } */ -/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */ +/* { dg-require-effective-target vsx_hw } */ +/* { dg-options "-mvsx -O2 -mfloat128" } */ /* * Test program to make sure we are getting more precision than the 53 bits we