diff mbox

, Re-fix PR 70381 (disable -mfloat128 by default) and add workaround for PR 70589

Message ID 20160407234442.GA9819@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner April 7, 2016, 11:44 p.m. UTC
After applying the fix for PR 70381 to not enable -mfloat128 by default, I
discovered the IEEE 128-bit floating point emulation routines in libgcc are no
longer being built.

The reason for this is the configuration test involved compiling this program:

	#pragma GCC target ("vsx,float128")
	__float128 add (__float128 *a) { return *a + *(a+1); }

to see if the __float128 support was enabled.  Unfortunately, I discovered that
you can't currently set/disable float128 via the target option attribute or
target pragmas. This is due to the fact that if -mfloat128 is disabled, the
__float128 and __ibm128 keywords are not created.

I raised this as a separate bug (70589).

This patch does several things:

   1)	It disables using float128 in target attributes or target pragmas.

   2)	It fixes the configure test for software emulation to just see if the
	ISA 2.06 (vsx) instruction set is available. The makefile options in
	the PowerPC libgcc build ensures that -mfloat128 is used. I used
	similar logic to detect ISA 3.0 to see if we have support for the IEEE
	128-bit floating point hardware.

   3)	I updated the documentation for -mfloat128.

   4)	I added two executable tests to verify that the float emulation is
	correct.  In working on adding the tests, I discovered I had the return
	value from main inverted, and the test would fail.

I have run a boostrap build and a make check to verify that the IEEE 128-bit
floating point emulator in libgcc is indeed built. Are these patches ok to
install in the GCC trunk?

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

	PR target/70589
	* 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-07  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-07  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.

Comments

David Edelsohn April 11, 2016, 1:04 p.m. UTC | #1
On Thu, Apr 7, 2016 at 7:44 PM, Michael Meissner
<meissner@linux.vnet.ibm.com> wrote:
> After applying the fix for PR 70381 to not enable -mfloat128 by default, I
> discovered the IEEE 128-bit floating point emulation routines in libgcc are no
> longer being built.
>
> The reason for this is the configuration test involved compiling this program:
>
>         #pragma GCC target ("vsx,float128")
>         __float128 add (__float128 *a) { return *a + *(a+1); }
>
> to see if the __float128 support was enabled.  Unfortunately, I discovered that
> you can't currently set/disable float128 via the target option attribute or
> target pragmas. This is due to the fact that if -mfloat128 is disabled, the
> __float128 and __ibm128 keywords are not created.
>
> I raised this as a separate bug (70589).
>
> This patch does several things:
>
>    1)   It disables using float128 in target attributes or target pragmas.
>
>    2)   It fixes the configure test for software emulation to just see if the
>         ISA 2.06 (vsx) instruction set is available. The makefile options in
>         the PowerPC libgcc build ensures that -mfloat128 is used. I used
>         similar logic to detect ISA 3.0 to see if we have support for the IEEE
>         128-bit floating point hardware.
>
>    3)   I updated the documentation for -mfloat128.
>
>    4)   I added two executable tests to verify that the float emulation is
>         correct.  In working on adding the tests, I discovered I had the return
>         value from main inverted, and the test would fail.
>
> I have run a boostrap build and a make check to verify that the IEEE 128-bit
> floating point emulator in libgcc is indeed built. Are these patches ok to
> install in the GCC trunk?
>
> [gcc]
> 2016-04-07  Michael Meissner  <meissner@linux.vnet.ibm.com>
>
>         PR target/70589
>         * 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-07  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-07  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.

This is okay.

Thanks, David
diff mbox

Patch

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	(revision 234797)
+++ gcc/config/rs6000/rs6000.c	(working copy)
@@ -34381,8 +34381,8 @@  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,		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: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 234797)
+++ gcc/doc/extend.texi	(working copy)
@@ -954,9 +954,13 @@  typedef _Complex float __attribute__((mo
 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: libgcc/configure.ac
===================================================================
--- libgcc/configure.ac	(revision 234797)
+++ libgcc/configure.ac	(working copy)
@@ -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;
      }
Index: libgcc/configure
===================================================================
--- libgcc/configure	(revision 234797)
+++ libgcc/configure	(working copy)
@@ -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: gcc/testsuite/gcc.target/powerpc/float128-1.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-1.c	(revision 0)
@@ -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;
+}
Index: gcc/testsuite/gcc.target/powerpc/float128-2.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
+++ gcc/testsuite/gcc.target/powerpc/float128-2.c	(revision 0)
@@ -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
+
+
+/*
+ * 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
+
+
+/*
+ * 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;
+}
+
+
+#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;
+}
+
+
+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: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 234797)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -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
 	}