rs6000-c.c (rs6000_cpu_cpp_builtins): Split -mfloat128 into -mfloat128-type that...
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Fri, 7 Oct 2016 18:58:10 +0000 (18:58 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Fri, 7 Oct 2016 18:58:10 +0000 (18:58 +0000)
[gcc]
2016-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>

* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Split
-mfloat128 into -mfloat128-type that enables the IEEE 128-bit
floating point type infrastructre, and -mfloat128 that enables the
keyword.  Define __FLOAT128__ if -mfloat128, and __FLOAT128_TYPE__
if -mfloat128-type.  Define __ibm128 to be long double by default.
* config/rs6000/rs6000.c (rs6000_debug_reg_global): Print whether
the IEEE 128-bit floating point type infrastructure should
automatically be enabled.
(rs6000_init_hard_regno_mode_ok): Switch to use -mfloat128-type
instead of -mfloat128 to enable KFmode.
(rs6000_option_override_internal): Split the option -mfloat128
into -mfloat128-type and -mfloat128.  On Linux PowerPC 64-bit
systems, automatically set -mfloat128-type, but don't enable it on
other operating systems.  Move setting the long double size and
IEEE quad support before the IEEE 128-bit floating point changes.
(rs6000_init_builtins): Do not create a unique type for __ibm128
if long double is IBM extended double, instead rely on __ibm128
being defined as 'long double'.  If -mfloat128-type and not
-mfloat128, create the KFmode type with an undocumented __ieee128
keyword.
(rs6000_init_libfuncs): Use -mfloat128-type instead of
-mfloat128 for tests about the types, but keep tests for
-mfloat128 to enable the keyword support.
(rs6000_complex_function_value): Likewise.
(rs6000_scalar_mode_supported_p): Likewise.
(rs6000_floatn_mode): Likewise.
(rs6000_c_mode_for_suffix): Likewise.
(rs6000_opt_masks): Add -mfloat128-type.
* config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add support for
-mfloat128-type being split from -mfloat128.  Add
-mfloat128-hardware, which was missing.
* config/rs6000/rs6000.opt (-mfloat128): Split -mfloat128 into
-mfloat128 and -mfloat128-type:
(-mfloat128-type): Likewise.
* config/rs6000/linux64.h (TARGET_FLOAT128_ENABLE_TYPE): Define so
that 64-bit Linux systems with enable -mfloat128-type by default
on VSX systems.
* config/rs6000/rs6000.h (TARGET_FLOAT128_ENABLE_TYPE): Likewise.
(FLOAT128_VECTOR_P): Switch IEEE 128-bit floating points to use
-mfloat128-type instead of -mfloat128.
(FLOAT128_2REG_P): Likewise.
(MASK_FLOAT128_TYPE): Likewise.
(ALTIVEC_ARG_MAX_RETURN): Likewise.
(RS6000_BTM_FLOAT128): Likewise.
(TARGET_FLOAT128): Poison old identifiers.
(OPTION_MASK_FLOAT128): Likewise.
(MASK_FLOAT128): Likewise.
* config/rs6000/rs6000.md (FP): Likewise.
(FLOAT128): Likewise.
(fix_trunc<mode>di2): Likewise.
(fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
(floatdi<mode>2): Likewise.
(floatuns<SDI:mode><IEEE128:mode>2): Likewise.
(neg<mode>2, FLOAT128 iterator): Likewise.
(abs<mode>2, FLOAT128 iterator): Likewise.
(ieee_128bit_negative_zero): Likewise.
(ieee_128bit_vsx_neg<mode>2): Likewise.
(ieee_128bit_vsx_neg<mode>2_internal): Likewise.
(ieee_128bit_vsx_abs<mode>2): Likewise.
(ieee_128bit_vsx_abs<mode>2_internal): Likewise.
(ieee_128bit_vsx_nabs<mode>2): Likewise.
(ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
(extendiftf2): Likewise.
(extendifkf2): Likewise.
(extendtfkf2): Likewise.
(trunciftf2): Likewise.
(truncifkf2): Likewise.
(trunckftf2): Likewise.
(trunctfif2): Likewise.
(extendkftf2): Likewise.
(trunctfkf2): Likewise.

[gcc/testsuite]
2016-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>

* gcc.target/powerpc/float128-type-1.c: New test to check that
PowerPC 64-bit Linux enables -mfloat128-type by default.
* gcc.target/powerpc/float128-type-2.c: Likewise.
* gcc.target/powerpc/float128-mix.c: Change error message to
reflect that __ibm128 is now #define'ed to be long double.

From-SVN: r240872

12 files changed:
gcc/ChangeLog
gcc/config/rs6000/linux64.h
gcc/config/rs6000/rs6000-c.c
gcc/config/rs6000/rs6000-cpus.def
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs6000.opt
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/float128-mix.c
gcc/testsuite/gcc.target/powerpc/float128-type-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/float128-type-2.c [new file with mode: 0644]

index fe68253b37a92c3b446e8a932668d7fe8cc10fb4..8c873c35d9688f4b66bbd90c11fc231045efe6f7 100644 (file)
@@ -1,3 +1,77 @@
+2016-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Split
+       -mfloat128 into -mfloat128-type that enables the IEEE 128-bit
+       floating point type infrastructre, and -mfloat128 that enables the
+       keyword.  Define __FLOAT128__ if -mfloat128, and __FLOAT128_TYPE__
+       if -mfloat128-type.  Define __ibm128 to be long double by default.
+       * config/rs6000/rs6000.c (rs6000_debug_reg_global): Print whether
+       the IEEE 128-bit floating point type infrastructure should
+       automatically be enabled.
+       (rs6000_init_hard_regno_mode_ok): Switch to use -mfloat128-type
+       instead of -mfloat128 to enable KFmode.
+       (rs6000_option_override_internal): Split the option -mfloat128
+       into -mfloat128-type and -mfloat128.  On Linux PowerPC 64-bit
+       systems, automatically set -mfloat128-type, but don't enable it on
+       other operating systems.  Move setting the long double size and
+       IEEE quad support before the IEEE 128-bit floating point changes.
+       (rs6000_init_builtins): Do not create a unique type for __ibm128
+       if long double is IBM extended double, instead rely on __ibm128
+       being defined as 'long double'.  If -mfloat128-type and not
+       -mfloat128, create the KFmode type with an undocumented __ieee128
+       keyword.
+       (rs6000_init_libfuncs): Use -mfloat128-type instead of
+       -mfloat128 for tests about the types, but keep tests for
+       -mfloat128 to enable the keyword support.
+       (rs6000_complex_function_value): Likewise.
+       (rs6000_scalar_mode_supported_p): Likewise.
+       (rs6000_floatn_mode): Likewise.
+       (rs6000_c_mode_for_suffix): Likewise.
+       (rs6000_opt_masks): Add -mfloat128-type.
+       * config/rs6000/rs6000-cpus.def (POWERPC_MASKS): Add support for
+       -mfloat128-type being split from -mfloat128.  Add
+       -mfloat128-hardware, which was missing.
+       * config/rs6000/rs6000.opt (-mfloat128): Split -mfloat128 into
+       -mfloat128 and -mfloat128-type:
+       (-mfloat128-type): Likewise.
+       * config/rs6000/linux64.h (TARGET_FLOAT128_ENABLE_TYPE): Define so
+       that 64-bit Linux systems with enable -mfloat128-type by default
+       on VSX systems.
+       * config/rs6000/rs6000.h (TARGET_FLOAT128_ENABLE_TYPE): Likewise.
+       (FLOAT128_VECTOR_P): Switch IEEE 128-bit floating points to use
+       -mfloat128-type instead of -mfloat128.
+       (FLOAT128_2REG_P): Likewise.
+       (MASK_FLOAT128_TYPE): Likewise.
+       (ALTIVEC_ARG_MAX_RETURN): Likewise.
+       (RS6000_BTM_FLOAT128): Likewise.
+       (TARGET_FLOAT128): Poison old identifiers.
+       (OPTION_MASK_FLOAT128): Likewise.
+       (MASK_FLOAT128): Likewise.
+       * config/rs6000/rs6000.md (FP): Likewise.
+       (FLOAT128): Likewise.
+       (fix_trunc<mode>di2): Likewise.
+       (fixuns_trunc<IEEE128:mode><SDI:mode>2): Likewise.
+       (floatdi<mode>2): Likewise.
+       (floatuns<SDI:mode><IEEE128:mode>2): Likewise.
+       (neg<mode>2, FLOAT128 iterator): Likewise.
+       (abs<mode>2, FLOAT128 iterator): Likewise.
+       (ieee_128bit_negative_zero): Likewise.
+       (ieee_128bit_vsx_neg<mode>2): Likewise.
+       (ieee_128bit_vsx_neg<mode>2_internal): Likewise.
+       (ieee_128bit_vsx_abs<mode>2): Likewise.
+       (ieee_128bit_vsx_abs<mode>2_internal): Likewise.
+       (ieee_128bit_vsx_nabs<mode>2): Likewise.
+       (ieee_128bit_vsx_nabs<mode>2_internal): Likewise.
+       (extendiftf2): Likewise.
+       (extendifkf2): Likewise.
+       (extendtfkf2): Likewise.
+       (trunciftf2): Likewise.
+       (truncifkf2): Likewise.
+       (trunckftf2): Likewise.
+       (trunctfif2): Likewise.
+       (extendkftf2): Likewise.
+       (trunctfkf2): Likewise.
+
 2016-10-07  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * simplify-rtx.c (simplify_immed_subreg): Zero-initialize tmp array
index e86b5d52ad6db214bd9644e9c8752790fa9423bc..0101ec0ac698fad979b6d0c55abd763a7074c7ab 100644 (file)
@@ -634,3 +634,9 @@ extern int dot_symbols;
   || (TARGET_GLIBC_MAJOR == 2 && TARGET_GLIBC_MINOR >= 19)
 #define RS6000_GLIBC_ATOMIC_FENV 1
 #endif
+
+/* The IEEE 128-bit emulator is only built on Linux systems.  Flag that we
+   should enable the type handling for KFmode on VSX systems even if we are not
+   enabling the __float128 keyword.  */
+#undef TARGET_FLOAT128_ENABLE_TYPE
+#define TARGET_FLOAT128_ENABLE_TYPE 1
index 8dfb53fc1873ceb4d8d42a5505289b8750fa8945..c98a54f995717920371cf8f0749b1acf3da12023 100644 (file)
@@ -425,10 +425,20 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
     builtin_define ("__RSQRTE__");
   if (TARGET_FRSQRTES)
     builtin_define ("__RSQRTEF__");
-  if (TARGET_FLOAT128)
+  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");
+
+  /* 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)
     {
index 401088f53043b20e3602672b7c103171aba2c863..e1786b24dab46411993e3af772d7836c00df1932 100644 (file)
                                 | OPTION_MASK_DIRECT_MOVE              \
                                 | OPTION_MASK_DLMZB                    \
                                 | OPTION_MASK_EFFICIENT_UNALIGNED_VSX  \
-                                | OPTION_MASK_FLOAT128                 \
+                                | OPTION_MASK_FLOAT128_HW              \
+                                | OPTION_MASK_FLOAT128_KEYWORD         \
+                                | OPTION_MASK_FLOAT128_TYPE            \
                                 | OPTION_MASK_FPRND                    \
                                 | OPTION_MASK_HTM                      \
                                 | OPTION_MASK_ISEL                     \
index e7e551daf4a6a3b8fd4e01fce185a9da91b761f3..49da4b629aeec04341e66877ab57921b8f82115d 100644 (file)
@@ -2718,6 +2718,9 @@ rs6000_debug_reg_global (void)
   fprintf (stderr, DEBUG_FMT_D, "Number of rs6000 builtins",
           (int)RS6000_BUILTIN_COUNT);
 
+  fprintf (stderr, DEBUG_FMT_D, "Enable float128 on VSX",
+          (int)TARGET_FLOAT128_ENABLE_TYPE);
+
   if (TARGET_VSX)
     fprintf (stderr, DEBUG_FMT_D, "VSX easy 64-bit scalar element",
             (int)VECTOR_ELEMENT_SCALAR_64BIT);
@@ -2956,7 +2959,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
 
   /* KF mode (IEEE 128-bit in VSX registers).  We do not have arithmetic, so
      only set the memory modes.  Include TFmode if -mabi=ieeelongdouble.  */
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       rs6000_vector_mem[KFmode] = VECTOR_VSX;
       rs6000_vector_align[KFmode] = 128;
@@ -3162,7 +3165,7 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_LFIWZX)
     rs6000_constraints[RS6000_CONSTRAINT_wz] = FLOAT_REGS;     /* DImode  */
 
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       rs6000_constraints[RS6000_CONSTRAINT_wq] = VSX_REGS;     /* KFmode  */
       if (FLOAT128_IEEE_P (TFmode))
@@ -3701,7 +3704,7 @@ rs6000_builtin_mask_calculate (void)
          | ((TARGET_DFP)                   ? RS6000_BTM_DFP       : 0)
          | ((TARGET_HARD_FLOAT)            ? RS6000_BTM_HARD_FLOAT : 0)
          | ((TARGET_LONG_DOUBLE_128)       ? RS6000_BTM_LDBL128   : 0)
-         | ((TARGET_FLOAT128)              ? RS6000_BTM_FLOAT128  : 0));
+         | ((TARGET_FLOAT128_TYPE)         ? RS6000_BTM_FLOAT128  : 0));
 }
 
 /* Implement TARGET_MD_ASM_ADJUST.  All asm statements are considered
@@ -4405,28 +4408,96 @@ rs6000_option_override_internal (bool global_init_p)
        }
     }
 
-  /* __float128 requires VSX support.  */
-  if (TARGET_FLOAT128 && !TARGET_VSX)
+  /* Set long double size before the IEEE 128-bit tests.  */
+  if (!global_options_set.x_rs6000_long_double_type_size)
     {
-      if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) != 0)
-       error ("-mfloat128 requires VSX support");
+      if (main_target_opt != NULL
+         && (main_target_opt->x_rs6000_long_double_type_size
+             != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
+       error ("target attribute or pragma changes long double size");
+      else
+       rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+    }
+
+  /* Set -mabi=ieeelongdouble on some old targets.  Note, AIX and Darwin
+     explicitly redefine TARGET_IEEEQUAD to 0, so those systems will not
+     pick up this default.  */
+#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
+  if (!global_options_set.x_rs6000_ieeequad)
+    rs6000_ieeequad = 1;
+#endif
+
+  /* Enable the default support for IEEE 128-bit floating point on Linux VSX
+     sytems, but don't enable the __float128 keyword.  */
+  if (TARGET_VSX && TARGET_LONG_DOUBLE_128
+      && (TARGET_FLOAT128_ENABLE_TYPE || TARGET_IEEEQUAD)
+      && ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_TYPE) == 0))
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_TYPE;
+
+  /* IEEE 128-bit floating point requires VSX support.  */
+  if (!TARGET_VSX)
+    {
+      if (TARGET_FLOAT128_KEYWORD)
+       {
+         if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) != 0)
+           error ("-mfloat128 requires VSX support");
+
+         rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+                               | OPTION_MASK_FLOAT128_KEYWORD
+                               | OPTION_MASK_FLOAT128_HW);
+       }
+
+      else if (TARGET_FLOAT128_TYPE)
+       {
+         if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_TYPE) != 0)
+           error ("-mfloat128-type requires VSX support");
 
-      rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128 | OPTION_MASK_FLOAT128_HW);
+         rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+                               | OPTION_MASK_FLOAT128_KEYWORD
+                               | OPTION_MASK_FLOAT128_HW);
+       }
     }
 
-  /* If we have -mfloat128 and full ISA 3.0 support, enable -mfloat128-hardware
-     by default.  */
-  if (TARGET_FLOAT128 && !TARGET_FLOAT128_HW
-      && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) == ISA_3_0_MASKS_IEEE
-      && !(rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW))
+  /* -mfloat128 and -mfloat128-hardware internally require the underlying IEEE
+      128-bit floating point support to be enabled.  */
+  if (!TARGET_FLOAT128_TYPE)
     {
-      rs6000_isa_flags |= OPTION_MASK_FLOAT128_HW;
-      if ((rs6000_isa_flags & OPTION_MASK_FLOAT128) != 0)
-       rs6000_isa_flags_explicit |= OPTION_MASK_FLOAT128_HW;
+      if (TARGET_FLOAT128_KEYWORD)
+       {
+         if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) != 0)
+           {
+             error ("-mfloat128 requires -mfloat128-type");
+             rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+                                   | OPTION_MASK_FLOAT128_KEYWORD
+                                   | OPTION_MASK_FLOAT128_HW);
+           }
+         else
+           rs6000_isa_flags |= OPTION_MASK_FLOAT128_TYPE;
+       }
+
+      if (TARGET_FLOAT128_HW)
+       {
+         if ((rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) != 0)
+           {
+             error ("-mfloat128-hardware requires -mfloat128-type");
+             rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
+           }
+         else
+           rs6000_isa_flags &= ~(OPTION_MASK_FLOAT128_TYPE
+                                 | OPTION_MASK_FLOAT128_KEYWORD
+                                 | OPTION_MASK_FLOAT128_HW);
+       }
     }
 
-  /* IEEE 128-bit floating point hardware instructions imply enabling
-     __float128.  */
+  /* If we have -mfloat128-type and full ISA 3.0 support, enable
+     -mfloat128-hardware by default.  However, don't enable the __float128
+     keyword.  If the user explicitly turned on -mfloat128-hardware, enable the
+     -mfloat128 option as well if it was not already set.  */
+  if (TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW
+      && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) == ISA_3_0_MASKS_IEEE
+      && !(rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW))
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_HW;
+
   if (TARGET_FLOAT128_HW
       && (rs6000_isa_flags & ISA_3_0_MASKS_IEEE) != ISA_3_0_MASKS_IEEE)
     {
@@ -4436,9 +4507,10 @@ rs6000_option_override_internal (bool global_init_p)
       rs6000_isa_flags &= ~OPTION_MASK_FLOAT128_HW;
     }
 
-  if (TARGET_FLOAT128_HW
-      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128) == 0)
-    rs6000_isa_flags |= OPTION_MASK_FLOAT128;
+  if (TARGET_FLOAT128_HW && !TARGET_FLOAT128_KEYWORD
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_HW) != 0
+      && (rs6000_isa_flags_explicit & OPTION_MASK_FLOAT128_KEYWORD) == 0)
+    rs6000_isa_flags |= OPTION_MASK_FLOAT128_KEYWORD;
 
   /* Print the options after updating the defaults.  */
   if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET)
@@ -4501,28 +4573,14 @@ rs6000_option_override_internal (bool global_init_p)
        }
     }
 
-  if (!global_options_set.x_rs6000_long_double_type_size)
-    {
-      if (main_target_opt != NULL
-         && (main_target_opt->x_rs6000_long_double_type_size
-             != RS6000_DEFAULT_LONG_DOUBLE_SIZE))
-       error ("target attribute or pragma changes long double size");
-      else
-       rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
-    }
-
-#if !defined (POWERPC_LINUX) && !defined (POWERPC_FREEBSD)
-  if (!global_options_set.x_rs6000_ieeequad)
-    rs6000_ieeequad = 1;
-#endif
-
   /* Disable VSX and Altivec silently if the user switched cpus to power7 in a
      target attribute or pragma which automatically enables both options,
      unless the altivec ABI was set.  This is set by default for 64-bit, but
      not for 32-bit.  */
   if (main_target_opt != NULL && !main_target_opt->x_rs6000_altivec_abi)
     rs6000_isa_flags &= ~((OPTION_MASK_VSX | OPTION_MASK_ALTIVEC
-                          | OPTION_MASK_FLOAT128)
+                          | OPTION_MASK_FLOAT128_TYPE
+                          | OPTION_MASK_FLOAT128_KEYWORD)
                          & ~rs6000_isa_flags_explicit);
 
   /* Enable Altivec ABI for AIX -maltivec.  */
@@ -16505,29 +16563,55 @@ rs6000_init_builtins (void)
      IFmode is the IBM extended 128-bit format that is a pair of doubles.
      TFmode will be either IEEE 128-bit floating point or the IBM double-double
      format that uses a pair of doubles, depending on the switches and
-     defaults.  */
-  if (TARGET_FLOAT128)
+     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 or __float128 if the type
+     is the same as long double.  Instead we add a #define for __ibm128 or
+     __float128 in rs6000_cpu_cpp_builtins to long double.  */
+  if (TARGET_IEEEQUAD || !TARGET_LONG_DOUBLE_128)
     {
       ibm128_float_type_node = make_node (REAL_TYPE);
       TYPE_PRECISION (ibm128_float_type_node) = 128;
       layout_type (ibm128_float_type_node);
       SET_TYPE_MODE (ibm128_float_type_node, IFmode);
 
-      ieee128_float_type_node = float128_type_node;
-
-      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
-                                             "__float128");
-
       lang_hooks.types.register_builtin_type (ibm128_float_type_node,
                                              "__ibm128");
     }
   else
+    ibm128_float_type_node = long_double_type_node;
+
+  if (TARGET_FLOAT128_KEYWORD)
+    {
+      ieee128_float_type_node = float128_type_node;
+      lang_hooks.types.register_builtin_type (ieee128_float_type_node,
+                                             "__float128");
+    }
+
+  else if (TARGET_FLOAT128_TYPE)
     {
-      /* All types must be nonzero, or self-test barfs during bootstrap.  */
-      ieee128_float_type_node = long_double_type_node;
-      ibm128_float_type_node = long_double_type_node;
+      ieee128_float_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (ibm128_float_type_node) = 128;
+      layout_type (ieee128_float_type_node);
+      SET_TYPE_MODE (ieee128_float_type_node, KFmode);
+
+      /* 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");
     }
 
+  else
+    ieee128_float_type_node = long_double_type_node;
+
   /* Initialize the modes for builtin_function_type, mapping a machine mode to
      tree type node.  */
   builtin_mode_to_type[QImode][0] = integer_type_node;
@@ -18316,7 +18400,7 @@ static void
 rs6000_init_libfuncs (void)
 {
   /* __float128 support.  */
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       init_float128_ibm (IFmode);
       init_float128_ieee (KFmode);
@@ -33425,7 +33509,7 @@ rs6000_mangle_type (const_tree type)
   /* Use a unique name for __float128 rather than trying to use "e" or "g". Use
      "g" for IBM extended double, no matter whether it is long double (using
      -mabi=ibmlongdouble) or the distinct __ibm128 type.  */
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       if (type == ieee128_float_type_node)
        return "U10__float128";
@@ -36397,7 +36481,7 @@ rs6000_complex_function_value (machine_mode mode)
   machine_mode inner = GET_MODE_INNER (mode);
   unsigned int inner_bytes = GET_MODE_UNIT_SIZE (mode);
 
-  if (TARGET_FLOAT128
+  if (TARGET_FLOAT128_TYPE
       && (mode == KCmode
          || (mode == TCmode && TARGET_IEEEQUAD)))
     regno = ALTIVEC_ARG_RETURN;
@@ -36804,7 +36888,7 @@ rs6000_scalar_mode_supported_p (machine_mode mode)
 
   if (DECIMAL_FLOAT_MODE_P (mode))
     return default_decimal_float_supported_p ();
-  else if (TARGET_FLOAT128 && (mode == KFmode || mode == IFmode))
+  else if (TARGET_FLOAT128_TYPE && (mode == KFmode || mode == IFmode))
     return true;
   else
     return default_scalar_mode_supported_p (mode);
@@ -36843,7 +36927,7 @@ rs6000_floatn_mode (int n, bool extended)
          return DFmode;
 
        case 64:
-         if (TARGET_FLOAT128)
+         if (TARGET_FLOAT128_KEYWORD)
            return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
          else
            return VOIDmode;
@@ -36867,7 +36951,7 @@ rs6000_floatn_mode (int n, bool extended)
          return DFmode;
 
        case 128:
-         if (TARGET_FLOAT128)
+         if (TARGET_FLOAT128_KEYWORD)
            return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
          else
            return VOIDmode;
@@ -36883,7 +36967,7 @@ rs6000_floatn_mode (int n, bool extended)
 static machine_mode
 rs6000_c_mode_for_suffix (char suffix)
 {
-  if (TARGET_FLOAT128)
+  if (TARGET_FLOAT128_TYPE)
     {
       if (suffix == 'q' || suffix == 'Q')
        return (FLOAT128_IEEE_P (TFmode)) ? TFmode : KFmode;
@@ -36984,7 +37068,8 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] =
   { "dlmzb",                   OPTION_MASK_DLMZB,              false, true  },
   { "efficient-unaligned-vsx", OPTION_MASK_EFFICIENT_UNALIGNED_VSX,
                                                                false, true  },
-  { "float128",                        OPTION_MASK_FLOAT128,           false, false },
+  { "float128",                        OPTION_MASK_FLOAT128_KEYWORD,   false, false },
+  { "float128-type",           OPTION_MASK_FLOAT128_TYPE,      false, false },
   { "float128-hardware",       OPTION_MASK_FLOAT128_HW,        false, false },
   { "fprnd",                   OPTION_MASK_FPRND,              false, true  },
   { "hard-dfp",                        OPTION_MASK_DFP,                false, true  },
index 446d388469e67fc0f456e14bed96861905cd4b63..ad5819385fe27b4d14c998440b9a35f5c4a40262 100644 (file)
@@ -363,6 +363,10 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 #define SET_TARGET_LINK_STACK(X) do { } while (0)
 #endif
 
+#ifndef TARGET_FLOAT128_ENABLE_TYPE
+#define TARGET_FLOAT128_ENABLE_TYPE 0
+#endif
+
 /* Return 1 for a symbol ref for a thread-local storage symbol.  */
 #define RS6000_SYMBOL_REF_TLS_P(RTX) \
   (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
@@ -449,12 +453,12 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 
 /* Helper macros to say whether a 128-bit floating point type can go in a
    single vector register, or whether it needs paired scalar values.  */
-#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE))
+#define FLOAT128_VECTOR_P(MODE) (TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (MODE))
 
 #define FLOAT128_2REG_P(MODE)                                          \
   (FLOAT128_IBM_P (MODE)                                               \
    || ((MODE) == TDmode)                                               \
-   || (!TARGET_FLOAT128 && FLOAT128_IEEE_P (MODE)))
+   || (!TARGET_FLOAT128_TYPE && FLOAT128_IEEE_P (MODE)))
 
 /* Return true for floating point that does not use a vector register.  */
 #define SCALAR_FLOAT_MODE_NOT_VECTOR_P(MODE)                           \
@@ -637,7 +641,7 @@ extern int rs6000_vector_align[];
 #define MASK_DIRECT_MOVE               OPTION_MASK_DIRECT_MOVE
 #define MASK_DLMZB                     OPTION_MASK_DLMZB
 #define MASK_EABI                      OPTION_MASK_EABI
-#define MASK_FLOAT128                  OPTION_MASK_FLOAT128
+#define MASK_FLOAT128_TYPE             OPTION_MASK_FLOAT128_TYPE
 #define MASK_FPRND                     OPTION_MASK_FPRND
 #define MASK_P8_FUSION                 OPTION_MASK_P8_FUSION
 #define MASK_HARD_FLOAT                        OPTION_MASK_HARD_FLOAT
@@ -1821,7 +1825,7 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
                           : (FP_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
 #define ALTIVEC_ARG_MAX_RETURN (DEFAULT_ABI != ABI_ELFv2               \
                                ? (ALTIVEC_ARG_RETURN                   \
-                                  + (TARGET_FLOAT128 ? 1 : 0))         \
+                                  + (TARGET_FLOAT128_TYPE ? 1 : 0))    \
                                : (ALTIVEC_ARG_RETURN + AGGR_ARG_NUM_REG - 1))
 
 /* Flags for the call/call_value rtl operations set up by function_arg */
@@ -2728,7 +2732,7 @@ extern int frame_pointer_needed;
 #define RS6000_BTM_HARD_FLOAT  MASK_SOFT_FLOAT /* Hardware floating point.  */
 #define RS6000_BTM_LDBL128     MASK_MULTIPLE   /* 128-bit long double.  */
 #define RS6000_BTM_64BIT       MASK_64BIT      /* 64-bit addressing.  */
-#define RS6000_BTM_FLOAT128    MASK_FLOAT128   /* IEEE 128-bit float.  */
+#define RS6000_BTM_FLOAT128    MASK_FLOAT128_TYPE /* IEEE 128-bit float.  */
 
 #define RS6000_BTM_COMMON      (RS6000_BTM_ALTIVEC                     \
                                 | RS6000_BTM_VSX                       \
@@ -2914,3 +2918,7 @@ extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
 extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
 
 #define TARGET_SUPPORTS_WIDE_INT 1
+
+#if (GCC_VERSION >= 3000)
+#pragma GCC poison TARGET_FLOAT128 OPTION_MASK_FLOAT128 MASK_FLOAT128
+#endif
index a9fabc181125061f392e240b924317087f49469f..e432a5a5411f07b32bcaa48ba0235bfc9572b374 100644 (file)
   (TF "TARGET_HARD_FLOAT
    && (TARGET_FPRS || TARGET_E500_DOUBLE)
    && TARGET_LONG_DOUBLE_128")
-  (IF "TARGET_FLOAT128")
-  (KF "TARGET_FLOAT128")
+  (IF "TARGET_LONG_DOUBLE_128")
+  (KF "TARGET_FLOAT128_TYPE")
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
                               (TF "FLOAT128_IEEE_P (TFmode)")])
 
 ; Iterator for 128-bit floating point
-(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128")
-                               (IF "TARGET_FLOAT128")
+(define_mode_iterator FLOAT128 [(KF "TARGET_FLOAT128_TYPE")
+                               (IF "TARGET_FLOAT128_TYPE")
                                (TF "TARGET_LONG_DOUBLE_128")])
 
 ; Iterator for signbit on 64-bit machines with direct move
 (define_expand "fix_trunc<mode>di2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "")
        (fix:DI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "fixuns_trunc<IEEE128:mode><SDI:mode>2"
   [(set (match_operand:SDI 0 "gpc_reg_operand" "")
        (unsigned_fix:SDI (match_operand:IEEE128 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
 (define_expand "floatdi<mode>2"
   [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
        (float:IEEE128 (match_operand:DI 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "floatuns<SDI:mode><IEEE128:mode>2"
   [(set (match_operand:IEEE128 0 "gpc_reg_operand" "")
        (unsigned_float:IEEE128 (match_operand:SDI 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], true);
   DONE;
          else
            gcc_unreachable ();
        }
-      else if (TARGET_FLOAT128)
+      else if (TARGET_FLOAT128_TYPE)
        {
          if (<MODE>mode == TFmode)
            emit_insn (gen_ieee_128bit_vsx_negtf2 (operands[0], operands[1]));
            FAIL;
          DONE;
        }
-      else if (TARGET_FLOAT128)
+      else if (TARGET_FLOAT128_TYPE)
        {
          if (<MODE>mode == TFmode)
            emit_insn (gen_ieee_128bit_vsx_abstf2 (operands[0], operands[1]));
 
 (define_expand "ieee_128bit_negative_zero"
   [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rtvec v = rtvec_alloc (16);
   int i, high;
   [(set (match_operand:IEEE128 0 "register_operand" "=wa")
        (neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
   [(set (match_operand:IEEE128 0 "register_operand" "=wa")
        (neg:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlxor %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
   [(set (match_operand:IEEE128 0 "register_operand" "=wa")
        (abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
   [(set (match_operand:IEEE128 0 "register_operand" "=wa")
        (abs:IEEE128 (match_operand:IEEE128 1 "register_operand" "wa")))
    (use (match_operand:V16QI 2 "register_operand" "v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlandc %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
         (abs:IEEE128
          (match_operand:IEEE128 1 "register_operand" "wa"))))
    (clobber (match_scratch:V16QI 2 "=v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW && FLOAT128_IEEE_P (<MODE>mode)"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW
+   && FLOAT128_IEEE_P (<MODE>mode)"
   "#"
   "&& 1"
   [(parallel [(set (match_dup 0)
         (abs:IEEE128
          (match_operand:IEEE128 1 "register_operand" "wa"))))
    (use (match_operand:V16QI 2 "register_operand" "v"))]
-  "TARGET_FLOAT128 && !TARGET_FLOAT128_HW"
+  "TARGET_FLOAT128_TYPE && !TARGET_FLOAT128_HW"
   "xxlor %x0,%x1,%x2"
   [(set_attr "type" "veclogical")])
 
 (define_expand "extendiftf2"
   [(set (match_operand:TF 0 "gpc_reg_operand" "")
        (float_extend:TF (match_operand:IF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "extendifkf2"
   [(set (match_operand:KF 0 "gpc_reg_operand" "")
        (float_extend:KF (match_operand:IF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "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" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "trunciftf2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
        (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "truncifkf2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
        (float_truncate:IF (match_operand:KF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "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" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_expand "trunctfif2"
   [(set (match_operand:IF 0 "gpc_reg_operand" "")
        (float_truncate:IF (match_operand:TF 1 "gpc_reg_operand" "")))]
-  "TARGET_FLOAT128"
+  "TARGET_FLOAT128_TYPE"
 {
   rs6000_expand_float128_convert (operands[0], operands[1], false);
   DONE;
 (define_insn_and_split "extendkftf2"
   [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa")
        (float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128 && TARGET_IEEEQUAD"
+  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
   "@
    #
    xxlor %x0,%x1,%x1"
 (define_insn_and_split "trunctfkf2"
   [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa")
        (float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))]
-  "TARGET_FLOAT128 && TARGET_IEEEQUAD"
+  "TARGET_FLOAT128_TYPE && TARGET_IEEEQUAD"
   "@
    #
    xxlor %x0,%x1,%x1"
index c79a439803c1b37c5e7858d960545aed1e9060fc..3e0717d2b06804f94eb93c30ae90124ff1af1e24 100644 (file)
@@ -645,8 +645,16 @@ mmodulo
 Target Undocumented Report Mask(MODULO) Var(rs6000_isa_flags)
 Generate the integer modulo instructions.
 
+; We want to enable the internal support for the IEEE 128-bit floating point
+; type without necessarily enabling the __float128 keyword.  This is to allow
+; Boost and other libraries that know about __float128 to work until the
+; official library support is finished.
+mfloat128-type
+Target Undocumented Mask(FLOAT128_TYPE) Var(rs6000_isa_flags)
+Allow the IEEE 128-bit types without requiring the __float128 keyword.
+
 mfloat128
-Target Report Mask(FLOAT128) Var(rs6000_isa_flags)
+Target Report Mask(FLOAT128_KEYWORD) Var(rs6000_isa_flags)
 Enable IEEE 128-bit floating point via the __float128 keyword.
 
 mfloat128-hardware
index a0fedffa0a6aa6f2d0ceab9343f98259ce24b1ab..0aa90ee5d780b89dabf347ff533712ecc9a044c4 100644 (file)
@@ -1,3 +1,11 @@
+2016-10-06  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/float128-type-1.c: New test to check that
+       PowerPC 64-bit Linux enables -mfloat128-type by default.
+       * gcc.target/powerpc/float128-type-2.c: Likewise.
+       * gcc.target/powerpc/float128-mix.c: Change error message to
+       reflect that __ibm128 is now #define'ed to be long double.
+
 2016-10-07  Steven G. Kargl  <kargl@gcc.gnu.org>
 
        PR fortran/77406
index 23cb9d5f3a26d8d504ade0e0d5d9b247cf98c612..d0cac20296308e72c8e5df172ac70e090a065c41 100644 (file)
@@ -4,13 +4,13 @@
 /* { dg-options "-O2 -mcpu=power7 -mfloat128" } */
 
 
-/* Test to make sure that __float128 and __ibm128 cannot be combined together.  */
-__float128 add (__float128 a, __ibm128 b)
+/* Test to make sure that __float128 and long double cannot be combined together.  */
+__float128 add (__float128 a, long double b)
 {
-  return a+b;  /* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+  return a+b;  /* { dg-error "__float128 and long double cannot be used in the same expression" "" } */
 }
 
-__ibm128 sub (__ibm128 a, __float128 b)
+__ibm128 sub (long double a, __float128 b)
 {
-  return a-b;  /* { dg-error "__float128 and __ibm128 cannot be used in the same expression" "" } */
+  return a-b;  /* { dg-error "__float128 and long double cannot be used in the same expression" "" } */
 }
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-type-1.c b/gcc/testsuite/gcc.target/powerpc/float128-type-1.c
new file mode 100644 (file)
index 0000000..a8326bd
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile { target { powerpc64*-*-linux* && lp64 } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O2" } */
+
+/* This test tests whether -mfloat128-type (which enables the underlying IEEE
+   128-bit floating point) is enabled by default on VSX Linux 64-bit systems,
+   even if the keywords __float128 and _Float128 (-mfloat128) are not enabled
+   via the -mfloat128 switch.  Test that power8 generates a call to the
+   __addkf3 emulation function.  */
+
+typedef double          __attribute__((__mode__(__KF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+
+f128_t
+add_scalar (f128_t a, f128_t b)
+{
+  return a+b;
+}
+
+
+f128c_t
+add_complex (f128c_t a, f128c_t b)
+{
+  return a+b;
+}
+
+/* { dg-final { scan-assembler "bl __addkf3" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-type-2.c b/gcc/testsuite/gcc.target/powerpc/float128-type-2.c
new file mode 100644 (file)
index 0000000..c5d6e35
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { powerpc64-*-linux* && lp64 } } } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power9" } } */
+/* { dg-options "-mcpu=power9 -O2" } */
+
+/* This test tests whether -mfloat128-type (which enables the underlying IEEE
+   128-bit floating point) is enabled by default on VSX Linux 64-bit systems,
+   even if the keywords __float128 and _Float128 (-mfloat128) are not enabled
+   via the -mfloat128 switch.  Test that power9 generates the xsaddqp
+   instruction.  */
+
+/* The effective target powerpc_float128_hw_ok is not used, as that will pass
+   -mfloat128.  */
+
+typedef double          __attribute__((__mode__(__KF__))) f128_t;
+typedef _Complex double __attribute__((__mode__(__KC__))) f128c_t;
+
+f128_t
+add_scalar (f128_t a, f128_t b)
+{
+  return a+b;
+}
+
+
+f128c_t
+add_complex (f128c_t a, f128c_t b)
+{
+  return a+b;
+}
+
+/* { dg-final { scan-assembler "xsaddqp" } } */