]> gcc.gnu.org Git - gcc.git/commitdiff
re PR target/70381 (On powerpc, -mfloat128 is on by default for all VSX systems)
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Mon, 11 Apr 2016 19:45:35 +0000 (19:45 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Mon, 11 Apr 2016 19:45:35 +0000 (19:45 +0000)
[gcc]
2016-04-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

PR target/70381
* config/rs6000/rs6000.c (rs6000_opt_masks): Disable using the
target attribute and pragma from changing the -mfloat128
and -mfloat128-hardware options.

* doc/extend.texi (Additional Floating Types): Document PowerPC
__float128 restrictions.

[libgcc]
2016-04-11  Michael Meissner  <meissner@linux.vnet.ibm.com>

PR target/70381
* configure.ac (powerpc*-*-linux*): Rework tests to build
__float128 emulation routines to not depend on using #pragma GCC
target to enable -mfloat128.
* configure: Regnerate.

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

PR target/70381
* gcc.target/powerpc/float128-1.c: New tests to make sure the
__float128 emulator is built and runs.
* gcc.target/powerpc/float128-1.c: Likewise.

* lib/target-supports.exp (check_ppc_float128_sw_available):
Rework tests for __float128 software and hardware
availability. Fix exit condition to return 0 on success.

From-SVN: r234884

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/float128-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/float128-2.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp
libgcc/ChangeLog
libgcc/configure
libgcc/configure.ac

index a59d245124a9c70da7708b203144b235ba643d3a..a01ee426005ca900822019db77c1877c3c7d1a3e 100644 (file)
@@ -1,3 +1,13 @@
+2016-04-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/70381
+       * config/rs6000/rs6000.c (rs6000_opt_masks): Disable using the
+       target attribute and pragma from changing the -mfloat128
+       and -mfloat128-hardware options.
+
+       * doc/extend.texi (Additional Floating Types): Document PowerPC
+       __float128 restrictions.
+
 2016-04-11  James Greenhalgh  <james.greenhalgh@arm.com>
 
        PR target/70133
index fd4b7cc5a7ee32cdc70f42a83fd04414662b3589..c63fa06aa1a07a0728c59175024b4fbb4608c141 100644 (file)
@@ -34381,8 +34381,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, true  },
-  { "float128-hardware",       OPTION_MASK_FLOAT128_HW,        false, true  },
+  { "float128",                        OPTION_MASK_FLOAT128,           false, false },
+  { "float128-hardware",       OPTION_MASK_FLOAT128_HW,        false, false },
   { "fprnd",                   OPTION_MASK_FPRND,              false, true  },
   { "hard-dfp",                        OPTION_MASK_DFP,                false, true  },
   { "htm",                     OPTION_MASK_HTM,                false, true  },
index 6e2702992c6722447c305c5d2c3cfa7131dd38e6..a5a8b23df275b70f047a3af9f79fa18a8542dcc0 100644 (file)
@@ -954,9 +954,13 @@ typedef _Complex float __attribute__((mode(TC))) _Complex128;
 typedef _Complex float __attribute__((mode(XC))) _Complex80;
 @end smallexample
 
-On PowerPC 64-bit Linux systems there are currently problems in using
-the complex @code{__float128} type.  When these problems are fixed,
-you would use:
+In order to use @code{__float128} and @code{__ibm128} on PowerPC Linux
+systems, you must use the @option{-mfloat128}. It is expected in
+future versions of GCC that @code{__float128} will be enabled
+automatically.  In addition, there are currently problems in using the
+complex @code{__float128} type.  When these problems are fixed, you
+would use the following syntax to declare @code{_Complex128} to be a
+complex @code{__float128} type:
 
 @smallexample
 typedef _Complex float __attribute__((mode(KC))) _Complex128;
index 3a0f142021b0fa5ba12adfa674f3b3ffc5c0abed..aa5c77c6bc66d7a8753ead2fb26d03dc4418ab7b 100644 (file)
@@ -1,3 +1,14 @@
+2016-04-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/70381
+       * gcc.target/powerpc/float128-1.c: New tests to make sure the
+       __float128 emulator is built and runs.
+       * gcc.target/powerpc/float128-1.c: Likewise.
+
+       * lib/target-supports.exp (check_ppc_float128_sw_available):
+       Rework tests for __float128 software and hardware
+       availability. Fix exit condition to return 0 on success.
+
 2016-04-11  James Greenhalgh  <james.greenhalgh@arm.com>
 
        PR target/70133
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-1.c b/gcc/testsuite/gcc.target/powerpc/float128-1.c
new file mode 100644 (file)
index 0000000..b8e71ce
--- /dev/null
@@ -0,0 +1,147 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+#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;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/float128-2.c b/gcc/testsuite/gcc.target/powerpc/float128-2.c
new file mode 100644 (file)
index 0000000..f517686
--- /dev/null
@@ -0,0 +1,226 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-require-effective-target ppc_float128_sw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128 -static-libgcc" } */
+
+/*
+ * Test program to make sure we are getting more precision than the 53 bits we
+ * get with IEEE double.
+ */
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+#ifndef TYPE
+#define TYPE __float128
+#endif
+
+#ifndef NO_INLINE
+#define NO_INLINE __attribute__((__noinline__))
+#endif
+
+static TYPE power_of_two (ssize_t) NO_INLINE;
+static TYPE calc1 (TYPE) NO_INLINE;
+static TYPE calc2 (TYPE) NO_INLINE;
+static TYPE calc3 (TYPE) NO_INLINE;
+
+#ifndef POWER2
+#define POWER2 60
+#endif
+
+\f
+/*
+ * Print TYPE in hex.
+ */
+
+
+#if defined(DEBUG) || defined(DEBUG2)
+static void print_hex (const char *prefix, TYPE, const char *suffix) NO_INLINE;
+
+#if defined (__i386__) || defined (__x86_64__) || defined (__LITTLE_ENDIAN__)
+#define ENDIAN_REVERSE(N, MAX)        ((MAX) - 1 - (N))
+
+#else
+#define ENDIAN_REVERSE(N, MAX)        (N)
+#endif
+
+static void
+print_hex (const char *prefix, TYPE value, const char *suffix)
+{
+  union {
+    TYPE f128;
+    unsigned char uc[sizeof (TYPE)];
+  } u;
+
+  size_t i;
+
+  u.f128 = value;
+  printf ("%s0x", prefix);
+  for (i = 0; i < sizeof (TYPE); i++)
+    printf ("%.2x", u.uc[ ENDIAN_REVERSE (i, sizeof (TYPE)) ]);
+
+  printf (", %24.2Lf%s", (long double)value, suffix);
+}
+#endif
+
+\f
+/*
+ * Return a power of two.
+ */
+
+static TYPE
+power_of_two (ssize_t num)
+{
+  TYPE ret = (TYPE) 1.0;
+  ssize_t i;
+
+  if (num >= 0)
+    {
+      for (i = 0; i < num; i++)
+       ret *= (TYPE) 2.0;
+    }
+  else
+    {
+      ssize_t num2 = -num;
+      for (i = 0; i < num2; i++)
+       ret /= (TYPE) 2.0;
+    }
+
+#ifdef DEBUG
+  printf ("power_of_two (%2ld)   = ", (long) num);
+  print_hex ("", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+#ifdef ADDSUB
+static TYPE add (TYPE a, TYPE b) NO_INLINE;
+static TYPE sub (TYPE a, TYPE b) NO_INLINE;
+
+static TYPE
+add (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("add, arg1           = ", a, "\n");
+  print_hex ("add, arg2           = ", b, "\n");
+#endif
+  c = a + b;
+#ifdef DEBUG
+  print_hex ("add, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+static TYPE
+sub (TYPE a, TYPE b)
+{
+  TYPE c;
+#ifdef DEBUG
+  print_hex ("sub, arg1           = ", a, "\n");
+  print_hex ("sub, arg2           = ", b, "\n");
+#endif
+  c = a - b;
+#ifdef DEBUG
+  print_hex ("sub, result         = ", c, "\n");
+#endif
+  return c;
+}
+
+#else
+#define add(x, y) ((x) + (y))
+#define sub(x, y) ((x) - (y))
+#endif
+
+/*
+ * Various calculations.  Add in 2**POWER2, and subtract 2**(POWER2-1) twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+  TYPE num2 = add (power_of_two (POWER2), num);
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc1 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc2 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc1 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc2 (TYPE num)
+{
+  TYPE num2 = sub (num, power_of_two (POWER2-1));
+  TYPE ret;
+
+#ifdef DEBUG
+  print_hex ("calc2 (before call) = ", num2, "\n");
+#endif
+
+  ret = calc3 (num2);
+
+#ifdef DEBUG
+  print_hex ("calc2 (after call)  = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+static TYPE
+calc3 (TYPE num)
+{
+  TYPE ret = sub (num, (((TYPE) 2.0) * power_of_two (POWER2-2)));
+
+#ifdef DEBUG
+  print_hex ("calc3               = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+\f
+int
+main (void)
+{
+  TYPE input, output;
+
+#ifdef DEBUG
+  printf ("Testing, %ld bytes\n", (long) sizeof (TYPE));
+#endif
+
+  input = power_of_two (-1);
+  if ((double)input != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Input should be 0.5:  ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  output = calc1 (input);
+  if ((double)output != 0.5)
+    {
+#if defined(DEBUG) || defined(DEBUG2)
+      print_hex ("Output should be 0.5: ", output, "\n");
+      return 1;
+#else
+      __builtin_abort ();
+#endif
+    }
+
+  return 0;
+}
index a3a7107cdf7df3390b5df0ca802de28358aeb950..3d44e1721dd69145696e9c275fa93ee1757a95a0 100644 (file)
@@ -1740,7 +1740,7 @@ proc check_ppc_float128_sw_available { } {
                int main()
                {
                    __float128 z = x + y;
-                   return (z == 3.0q);
+                   return (z != 3.0q);
                }
            } $options
        }
@@ -1759,7 +1759,7 @@ proc check_ppc_float128_hw_available { } {
             || [istarget *-*-darwin*]} {
            expr 0
        } else {
-           set options "-mfloat128-hardware"
+           set options "-mfloat128 -mvsx -mfloat128-hardware -mpower9-vector"
            check_runtime_nocache ppc_float128_hw_available {
                volatile __float128 x = 1.0q;
                volatile __float128 y = 2.0q;
@@ -1769,7 +1769,7 @@ proc check_ppc_float128_hw_available { } {
                    __float128 w = -1.0q;
 
                    __asm__ ("xsaddqp %0,%1,%2" : "+v" (w) : "v" (x), "v" (y));
-                   return ((z == 3.0q) && (z == w);
+                   return ((z != 3.0q) || (z != w);
                }
            } $options
        }
index 6011d2cccfb1ed726bf597702e3327b5f8c6e196..2a1386283262ce827eee8ef2de2b5cf50b90978d 100644 (file)
@@ -1,3 +1,11 @@
+2016-04-11  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       PR target/70381
+       * configure.ac (powerpc*-*-linux*): Rework tests to build
+       __float128 emulation routines to not depend on using #pragma GCC
+       target to enable -mfloat128.
+       * configure: Regnerate.
+
 2016-04-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR target/67172
index f3f360512c46589973a6fdfbd68feb5658d85063..e7d6c75a6f76eff959dde7136a5775c42a0fde19 100644 (file)
@@ -4767,16 +4767,20 @@ esac
 esac
 
 case ${host} in
+# At present, we cannot turn -mfloat128 on via #pragma GCC target,
+# so just check if we have VSX (ISA 2.06) support to build the
+# software libraries, and whether the assembler can handle xsaddqp
+# for hardware support.
 powerpc*-*-linux*)
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do __float128" >&5
-$as_echo_n "checking whether the PowerPC compiler can do __float128... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 2.06 to build __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 2.06 to build __float128 libraries... " >&6; }
 if test "${libgcc_cv_powerpc_float128+set}" = set; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#pragma GCC target ("vsx,float128")
-     __float128 add (__float128 *a) { return *a + *(a+1); }
+#pragma GCC target ("vsx")
+     vector double dadd (vector double a, vector double b) { return a + b; }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
   libgcc_cv_powerpc_float128=yes
@@ -4788,21 +4792,21 @@ fi
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcc_cv_powerpc_float128" >&5
 $as_echo "$libgcc_cv_powerpc_float128" >&6; }
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the PowerPC compiler can do hardware __float128" >&5
-$as_echo_n "checking whether the PowerPC compiler can do hardware __float128... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PowerPC ISA 3.0 to build hardware __float128 libraries" >&5
+$as_echo_n "checking for PowerPC ISA 3.0 to build hardware __float128 libraries... " >&6; }
 if test "${libgcc_cv_powerpc_float128_hw+set}" = set; then :
   $as_echo_n "(cached) " >&6
 else
   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
-#pragma GCC target ("cpu=power9,float128,float128-hardware")
+#pragma GCC target ("vsx,power9-vector")
      #include <sys/auxv.h>
      #ifndef AT_PLATFORM
      #error "AT_PLATFORM is not defined"
      #endif
-     __float128 add (__float128 a, __float128 b)
+     vector unsigned char (vector unsigned char a, vector unsigned char b)
      {
-       __float128 ret;
+       vector unsigned char ret;
        __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
        return ret;
      }
index 897259e62bc304cb02193f75f7ef1b05a9a5d520..269997f23e25ef9253f799afdfee616e04699265 100644 (file)
@@ -374,26 +374,30 @@ esac
 esac
 
 case ${host} in
+# At present, we cannot turn -mfloat128 on via #pragma GCC target,
+# so just check if we have VSX (ISA 2.06) support to build the
+# software libraries, and whether the assembler can handle xsaddqp
+# for hardware support.
 powerpc*-*-linux*)
-  AC_CACHE_CHECK([whether the PowerPC compiler can do __float128],
+  AC_CACHE_CHECK([for PowerPC ISA 2.06 to build __float128 libraries],
                 [libgcc_cv_powerpc_float128],
                 [AC_COMPILE_IFELSE(
-    [#pragma GCC target ("vsx,float128")
-     __float128 add (__float128 *a) { return *a + *(a+1); }],
+    [#pragma GCC target ("vsx")
+     vector double dadd (vector double a, vector double b) { return a + b; }],
     [libgcc_cv_powerpc_float128=yes],
     [libgcc_cv_powerpc_float128=no])])
 
-  AC_CACHE_CHECK([whether the PowerPC compiler can do hardware __float128],
+  AC_CACHE_CHECK([for PowerPC ISA 3.0 to build hardware __float128 libraries],
                 [libgcc_cv_powerpc_float128_hw],
                 [AC_COMPILE_IFELSE(
-    [#pragma GCC target ("cpu=power9,float128,float128-hardware")
+    [#pragma GCC target ("vsx,power9-vector")
      #include <sys/auxv.h>
      #ifndef AT_PLATFORM
      #error "AT_PLATFORM is not defined"
      #endif
-     __float128 add (__float128 a, __float128 b)
+     vector unsigned char (vector unsigned char a, vector unsigned char b)
      {
-       __float128 ret;
+       vector unsigned char ret;
        __asm__ ("xsaddqp %0,%1,%2" : "=v" (ret) : "v" (a), "v" (b));
        return ret;
      }
This page took 0.191822 seconds and 5 git commands to generate.