These patches are patches to the testsuite to add tests for IEEE 128-bit
floating point.  Both -mfloat128-vsx and -mfloat128-ref are tested in two
tests.  The first is a simple test whether it works, and the second test
insures that we have at least 60 bits of accuracy in the mantissa.

2014-07-15  Michael Meissner  <meiss...@linux.vnet.ibm.com>

        * gcc.target/powerpc/float128-1.c: New tests for IEEE 128-bit
        floating point support.
        * gcc.target/powerpc/float128-2.c: Likewise.
        * gcc.target/powerpc/float128-3.c: Likewise.
        * gcc.target/powerpc/float128-4.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/testsuite/gcc.target/powerpc/float128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-1.c       
(.../svn+ssh://meiss...@gcc.gnu.org/svn/gcc/trunk)      (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-1.c       (revision 212529)
@@ -0,0 +1,27 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128-vsx" } */
+
+int
+main (void)
+{
+  __float128 one = 1.0q;
+  __float128 two = 2.0q;
+  __float128 three = 3.0q;
+  __float128 four = 4.0q;
+  __float128 result = ((1.0q + 2.0q) * 3.0q) / 4.0q;
+  __float128 xresult;
+
+  __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));
+
+  xresult = ((one + two) * three) / four;
+  if (result != xresult)
+    __builtin_abort ();
+
+  return 0;
+}
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)      (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-2.c       (revision 212529)
@@ -0,0 +1,27 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target ppc_recip_hw } */
+/* { dg-options "-O2 -mfloat128-ref" } */
+
+int
+main (void)
+{
+  __float128 one = 1.0q;
+  __float128 two = 2.0q;
+  __float128 three = 3.0q;
+  __float128 four = 4.0q;
+  __float128 result = ((1.0q + 2.0q) * 3.0q) / 4.0q;
+  __float128 xresult;
+
+  __asm__ (" #prevent constant folding, %0" : "+d" (one));
+  __asm__ (" #prevent constant folding, %0" : "+d" (two));
+  __asm__ (" #prevent constant folding, %0" : "+d" (three));
+  __asm__ (" #prevent constant folding, %0" : "+d" (four));
+
+  xresult = ((one + two) * three) / four;
+  if (result != xresult)
+    __builtin_abort ();
+
+  return 0;
+}
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)      (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-3.c       (revision 212529)
@@ -0,0 +1,182 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target vsx_hw } */
+/* { dg-options "-mcpu=power7 -O2 -mfloat128-vsx" } */
+
+/*
+ * 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;
+
+
+/*
+ * Print TYPE in hex.
+ */
+
+
+#ifdef DEBUG
+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
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * Various calculations.  Add in 2**60, and subtract 2**59 twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+  TYPE num2 = power_of_two (60) + 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 = num - power_of_two (59);
+  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 = num - (((TYPE) 2.0) * power_of_two (58));
+
+#ifdef DEBUG
+  print_hex ("calc3               = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+
+int
+main (void)
+{
+  TYPE input, output;
+
+#ifdef DEBUG
+  printf ("Testing %s, %ld bytes\n", TYPE_NAME, (long) sizeof (TYPE));
+#endif
+
+  input = power_of_two (-1);
+  output = calc1 (input);
+
+  if (input != (TYPE) 0.5)
+    {
+#ifdef DEBUG
+      print_hex ("Input should be 0.5:  ", output, "\n");
+#endif
+      __builtin_abort ();
+    }
+
+  if (output != (TYPE) 0.5)
+    {
+#ifdef DEBUG
+      print_hex ("Output should be 0.5: ", output, "\n");
+#endif
+      __builtin_abort ();
+    }
+
+  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)      (revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-4.c       (revision 212529)
@@ -0,0 +1,182 @@
+/* { dg-do run { target { powerpc*-*-linux* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */
+/* { dg-require-effective-target ppc_recip_hw } */
+/* { dg-options "-O2 -mfloat128-ref" } */
+
+/*
+ * 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;
+
+
+/*
+ * Print TYPE in hex.
+ */
+
+
+#ifdef DEBUG
+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
+
+
+/*
+ * 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;
+}
+
+
+/*
+ * Various calculations.  Add in 2**60, and subtract 2**59 twice, and we should
+ * get the original value.
+ */
+
+static TYPE
+calc1 (TYPE num)
+{
+  TYPE num2 = power_of_two (60) + 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 = num - power_of_two (59);
+  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 = num - (((TYPE) 2.0) * power_of_two (58));
+
+#ifdef DEBUG
+  print_hex ("calc3               = ", ret, "\n");
+#endif
+
+  return ret;
+}
+
+
+int
+main (void)
+{
+  TYPE input, output;
+
+#ifdef DEBUG
+  printf ("Testing %s, %ld bytes\n", TYPE_NAME, (long) sizeof (TYPE));
+#endif
+
+  input = power_of_two (-1);
+  output = calc1 (input);
+
+  if (input != (TYPE) 0.5)
+    {
+#ifdef DEBUG
+      print_hex ("Input should be 0.5:  ", output, "\n");
+#endif
+      __builtin_abort ();
+    }
+
+  if (output != (TYPE) 0.5)
+    {
+#ifdef DEBUG
+      print_hex ("Output should be 0.5: ", output, "\n");
+#endif
+      __builtin_abort ();
+    }
+
+  return 0;
+}

Reply via email to