diff mbox series

rs6000: Add vgnb

Message ID 20200508024502.106596-1-wschmidt@linux.ibm.com
State New
Headers show
Series rs6000: Add vgnb | expand

Commit Message

Bill Schmidt May 8, 2020, 2:45 a.m. UTC
From: Kelvin Nilsen <kelvin@gcc.gnu.org>

Add support for the vgnb instruction, which gathers every Nth bit
per vector element.

Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
regressions.  Is this okay for master?

Thanks,
Bill

[gcc]

2020-05-07  Kelvin Nilsen  <kelvin@gcc.gnu.org>
	    Bill Schmidt  <wschmidt@linux.ibm.com>

	* config/rs6000/altivec.h (vec_gnb): New #define.
	* config/rs6000/altivec.md (UNSPEC_VGNB): New constant.
	(vgnb): New insn.
	* config/rs6000/rs6000-builtin.def (BU_FUTURE_OVERLOAD_1): New
	#define.
	(BU_FUTURE_OVERLOAD_2): Likewise.
	(BU_FUTURE_OVERLOAD_3): Likewise.
	(__builtin_altivec_gnb): New built-in function.
	(__buiiltin_vec_gnb): New overloaded built-in function.
	* config/rs6000/rs6000-call.c (altivec_overloaded_builtins):
	Define overloaded forms of __builtin_vec_gnb.
	(rs6000_expand_binop_builtin): Add error checking for 2nd argument
	of __builtin_vec_gnb.
	(builtin_function_type): Mark return value and arguments unsigned
	for FUTURE_BUILTIN_VGNB.
	* doc/extend.texi (PowerPC AltiVec Built-in Functions Available
	for a Future Architecture): Add description of vec_gnb built-in
	function.

[gcc/testsuite]

2020-05-07  Kelvin Nilsen  <kelvin@gcc.gnu.org>
	    Bill Schmidt  <wschmidt@linux.ibm.com>

	* gcc.target/powerpc/vec-gnb-0.c: New test.
	* gcc.target/powerpc/vec-gnb-1.c: New test.
	* gcc.target/powerpc/vec-gnb-10.c: New test.
	* gcc.target/powerpc/vec-gnb-2.c: New test.
	* gcc.target/powerpc/vec-gnb-3.c: New test.
	* gcc.target/powerpc/vec-gnb-4.c: New test.
	* gcc.target/powerpc/vec-gnb-5.c: New test.
	* gcc.target/powerpc/vec-gnb-6.c: New test.
	* gcc.target/powerpc/vec-gnb-7.c: New test.
	* gcc.target/powerpc/vec-gnb-8.c: New test.
	* gcc.target/powerpc/vec-gnb-9.c: New test.
---
 gcc/config/rs6000/altivec.h                   |  2 +
 gcc/config/rs6000/altivec.md                  | 10 +++
 gcc/config/rs6000/rs6000-builtin.def          | 29 +++++++
 gcc/config/rs6000/rs6000-call.c               | 26 +++++++
 gcc/doc/extend.texi                           | 18 ++++-
 gcc/testsuite/gcc.target/powerpc/vec-gnb-0.c  | 75 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c  | 75 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-10.c | 72 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c  | 73 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-3.c  | 72 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-4.c  | 71 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-5.c  | 71 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-6.c  | 71 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-7.c  | 71 ++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-8.c  | 75 +++++++++++++++++++
 gcc/testsuite/gcc.target/powerpc/vec-gnb-9.c  | 74 ++++++++++++++++++
 16 files changed, 884 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-0.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-10.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-3.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-4.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-5.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-6.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-7.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-8.c
 create mode 100644 gcc/testsuite/gcc.target/powerpc/vec-gnb-9.c

Comments

Segher Boessenkool May 8, 2020, 9:06 p.m. UTC | #1
On Thu, May 07, 2020 at 09:45:02PM -0500, Bill Schmidt wrote:
> From: Kelvin Nilsen <kelvin@gcc.gnu.org>
> 
> Add support for the vgnb instruction, which gathers every Nth bit
> per vector element.
> 
> Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no
> regressions.  Is this okay for master?

This one looks fine as well.  All (up to here ;-) ) are okay for trunk,
unless David sees something (I have seen these patches too often before
already, that causes blind spots :-) )  Thanks!


Segher
diff mbox series

Patch

diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h
index 12dfcd8d2bf..b6ecad6911d 100644
--- a/gcc/config/rs6000/altivec.h
+++ b/gcc/config/rs6000/altivec.h
@@ -694,6 +694,8 @@  __altivec_scalar_pred(vec_any_nle,
 #define vec_pdep(a, b)	__builtin_altivec_vpdepd (a, b)
 #define vec_pext(a, b)	__builtin_altivec_vpextd (a, b)
 
+/* Overloaded built-in functions for future architecture.  */
+#define vec_gnb(a, b)	__builtin_vec_gnb (a, b)
 #endif
 
 #endif /* _ALTIVEC_H */
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 33ba57855bc..7cebb58331e 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -162,6 +162,7 @@  (define_c_enum "unspec"
    UNSPEC_VRLNM
    UNSPEC_VCLZDM
    UNSPEC_VCTZDM
+   UNSPEC_VGNB
    UNSPEC_VPDEPD
    UNSPEC_VPEXTD
 ])
@@ -4136,6 +4137,15 @@  (define_insn "vpextd"
    "vpextd %0,%1,%2"
    [(set_attr "type" "vecsimple")])
 
+(define_insn "vgnb"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+        (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v")
+	            (match_operand:QI 2 "u3bit_cint_operand" "n")]
+         UNSPEC_VGNB))]
+   "TARGET_FUTURE"
+   "vgnb %0,%1,%2"
+   [(set_attr "type" "vecsimple")])
+
 
 (define_expand "bcd<bcd_add_sub>_<code>"
   [(parallel [(set (reg:CCFP CR6_REGNO)
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 776fc542ebf..e25249b5418 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -969,6 +969,30 @@ 
 		     | RS6000_BTC_TERNARY),				\
 		    CODE_FOR_ ## ICODE)			/* ICODE */
 
+#define BU_FUTURE_OVERLOAD_1(ENUM, NAME)				\
+  RS6000_BUILTIN_1 (FUTURE_BUILTIN_VEC_ ## ENUM,	/* ENUM */	\
+		    "__builtin_vec_" NAME,		/* NAME */	\
+		    RS6000_BTM_FUTURE,			/* MASK */	\
+		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
+		     | RS6000_BTC_UNARY),				\
+		    CODE_FOR_nothing)			/* ICODE */
+
+#define BU_FUTURE_OVERLOAD_2(ENUM, NAME)				\
+  RS6000_BUILTIN_2 (FUTURE_BUILTIN_VEC_ ## ENUM,	/* ENUM */	\
+		    "__builtin_vec_" NAME,		/* NAME */	\
+		    RS6000_BTM_FUTURE,			/* MASK */	\
+		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
+		     | RS6000_BTC_BINARY),				\
+		    CODE_FOR_nothing)			/* ICODE */
+
+#define BU_FUTURE_OVERLOAD_3(ENUM, NAME)				\
+  RS6000_BUILTIN_3 (FUTURE_BUILTIN_VEC_ ## ENUM,	/* ENUM */	\
+		    "__builtin_vec_" NAME,		/* NAME */	\
+		    RS6000_BTM_FUTURE,			/* MASK */	\
+		    (RS6000_BTC_OVERLOADED		/* ATTR */	\
+		     | RS6000_BTC_TERNARY),				\
+		    CODE_FOR_nothing)			/* ICODE */
+
 #endif
 
 
@@ -2520,6 +2544,11 @@  BU_FUTURE_V_2 (VCLZDM, "vclzdm", CONST, vclzdm)
 BU_FUTURE_V_2 (VCTZDM, "vctzdm", CONST, vctzdm)
 BU_FUTURE_V_2 (VPDEPD, "vpdepd", CONST, vpdepd)
 BU_FUTURE_V_2 (VPEXTD, "vpextd", CONST, vpextd)
+BU_FUTURE_V_2 (VGNB, "vgnb", CONST, vgnb)
+
+/* Future architecture overloaded vector built-ins.  */
+BU_FUTURE_OVERLOAD_2 (GNB, "gnb")
+
 
 /* 1 argument crypto functions.  */
 BU_CRYPTO_1 (VSBOX,		"vsbox",	  CONST, crypto_vsbox_v2di)
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index ab6ba576605..952f17c6854 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -5505,6 +5505,17 @@  const struct altivec_builtin_types altivec_overloaded_builtins[] = {
     RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI,
     RS6000_BTI_INTSI, RS6000_BTI_INTSI },
 
+  /* FUTURE overloaded builtin functions, */
+  { FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
+    RS6000_BTI_unsigned_V16QI, RS6000_BTI_UINTQI, 0 },
+  { FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
+    RS6000_BTI_unsigned_V8HI, RS6000_BTI_UINTQI, 0 },
+  { FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
+    RS6000_BTI_unsigned_V4SI, RS6000_BTI_UINTQI, 0 },
+  { FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
+    RS6000_BTI_unsigned_V2DI, RS6000_BTI_UINTQI, 0 },
+  { FUTURE_BUILTIN_VEC_GNB, FUTURE_BUILTIN_VGNB, RS6000_BTI_unsigned_long_long,
+    RS6000_BTI_unsigned_V1TI, RS6000_BTI_UINTQI, 0 },
   { RS6000_BUILTIN_NONE, RS6000_BUILTIN_NONE, 0, 0, 0, 0 }
 };
 
@@ -8829,6 +8840,20 @@  rs6000_expand_binop_builtin (enum insn_code icode, tree exp, rtx target)
 	  return CONST0_RTX (tmode);
 	}
     }
+  else if (icode == CODE_FOR_vgnb)
+    {
+      /* Only allow unsigned literals in range 2..7.  */
+      /* Note that arg1 is second operand.  */
+      STRIP_NOPS (arg1);
+      if (TREE_CODE (arg1) != INTEGER_CST
+	  || (TREE_INT_CST_LOW (arg1) & ~7)
+	  || !IN_RANGE (TREE_INT_CST_LOW (arg1), 2, 7))
+	{
+	  error ("argument 2 must be unsigned literal between "
+		 "2 and 7 inclusive");
+	  return CONST0_RTX (tmode);
+	}
+    }
   else if (icode == CODE_FOR_altivec_vsplth)
     {
       /* Only allow 3-bit unsigned literals.  */
@@ -12928,6 +12953,7 @@  builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0,
     case P8V_BUILTIN_ORC_V1TI_UNS:
     case FUTURE_BUILTIN_VCLZDM:
     case FUTURE_BUILTIN_VCTZDM:
+    case FUTURE_BUILTIN_VGNB:
     case FUTURE_BUILTIN_VPDEPD:
     case FUTURE_BUILTIN_VPEXTD:
       h.uns_p[0] = 1;
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 23c7aa6fb79..4a4d3bd0918 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -20713,6 +20713,23 @@  Perform a vector count trailing zeros under bit mask operation, as if
 implemented by the Future @code{vctzdm} instruction.
 @findex vec_ctzm
 
+@smallexample
+@exdent vector unsigned long long int
+@exdent vec_gnb (vector unsigned char, const unsigned char)
+@exdent vector unsigned long long int
+@exdent vec_gnb (vector unsigned short, const unsigned char)
+@exdent vector unsigned long long int
+@exdent vec_gnb (vector unsigned int, const unsigned char)
+@exdent vector unsigned long long int
+@exdent vec_gnb (vector unsigned long long int, const unsigned char)
+@exdent vector unsigned long long int
+@exdent vec_gnb (vector unsigned __int128, const unsigned char)
+@end smallexample
+Perform a 128-bit vector gather  operation, as if implemented by the Future
+@code{vgnb} instruction.  The second argument must be a literal
+integer value between 2 and 7 inclusive.
+@findex vec_gnb
+
 @smallexample
 @exdent vector unsigned long long int
 @exdent vec_pdep (vector unsigned long long int, vector unsigned long long int)
@@ -21452,7 +21469,6 @@  v8qi __builtin_vis_fpmaxu8 (v8qi, v8qi);
 v4hi __builtin_vis_fpmaxu16 (v4hi, v4hi);
 v2si __builtin_vis_fpmaxu32 (v2si, v2si);
 
-
 v8qi __builtin_vis_fpmin8 (v8qi, v8qi);
 v4hi __builtin_vis_fpmin16 (v4hi, v4hi);
 v2si __builtin_vis_fpmin32 (v2si, v2si);
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-0.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-0.c
new file mode 100644
index 00000000000..a95c29cf31d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-0.c
@@ -0,0 +1,75 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned char source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned char source_a = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_b = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+  vector unsigned char source_c = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_d = {
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvgnb\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
new file mode 100644
index 00000000000..e8ceed55994
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-1.c
@@ -0,0 +1,75 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned char source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned char source_a = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_b = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+  vector unsigned char source_c = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_d = {
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-10.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-10.c
new file mode 100644
index 00000000000..73ff0d9fea7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-10.c
@@ -0,0 +1,72 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+unsigned long long int
+do_vec_gnb (vector unsigned char source, unsigned char stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 0);	/* { dg-error "between 2 and 7" } */
+    case 3:
+      return vec_gnb (source, -1);	/* { dg-error "between 2 and 7" } */
+    case 4:
+      return vec_gnb (source, 8);	/* { dg-error "between 2 and 7" } */
+    case 5:
+      return vec_gnb (source, 1);	/* { dg-error "between 2 and 7" } */
+    case 6:
+      return vec_gnb (source, stride);	/* { dg-error "unsigned literal" } */
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned char source_a = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_b = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+  vector unsigned char source_c = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 };
+  vector unsigned char source_d = {
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+    0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
new file mode 100644
index 00000000000..eb51a8db219
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-2.c
@@ -0,0 +1,73 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned short int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned short int source_a = { 0, 0, 0, 0, 0, 0, 0x8888, 0x8888 };
+  vector unsigned short int source_b = {
+    0, 0, 0, 0, 0x8080, 0x8080, 0x8080, 0x8080 };
+  vector unsigned short int source_c = {
+    0, 0, 0, 0, 0x8888, 0x8888, 0x8888, 0x8888 };
+  vector unsigned short int source_d = {
+    0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvgnb\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-3.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-3.c
new file mode 100644
index 00000000000..f36b91a83e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-3.c
@@ -0,0 +1,72 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned short int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned short int source_a = { 0, 0, 0, 0, 0, 0, 0x8888, 0x8888 };
+  vector unsigned short int source_b = {
+    0, 0, 0, 0, 0x8080, 0x8080, 0x8080, 0x8080 };
+  vector unsigned short int source_c = {
+    0, 0, 0, 0, 0x8888, 0x8888, 0x8888, 0x8888 };
+  vector unsigned short int source_d = {
+    0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-4.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-4.c
new file mode 100644
index 00000000000..df312ae1b28
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-4.c
@@ -0,0 +1,71 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned int source_a = { 0, 0, 0, 0x88888888 };
+  vector unsigned int source_b = { 0, 0, 0x80808080, 0x80808080 };
+  vector unsigned int source_c = { 0, 0, 0x88888888, 0x88888888 };
+  vector unsigned int source_d =
+    { 0x80808080, 0x80808080, 0x80808080, 0x80808080 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvgnb\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-5.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-5.c
new file mode 100644
index 00000000000..1c3c3fa72c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-5.c
@@ -0,0 +1,71 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned int source_a = { 0, 0, 0, 0x88888888 };
+  vector unsigned int source_b = { 0, 0, 0x80808080, 0x80808080 };
+  vector unsigned int source_c = { 0, 0, 0x88888888, 0x88888888 };
+  vector unsigned int source_d =
+    { 0x80808080, 0x80808080, 0x80808080, 0x80808080 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-6.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-6.c
new file mode 100644
index 00000000000..a6dc78a3e98
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-6.c
@@ -0,0 +1,71 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned long long int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned long long int source_a = { 0, 0x8888888800000000ull };
+  vector unsigned long long int source_b = { 0, 0x8080808080808080ull };
+  vector unsigned long long int source_c = { 0, 0x8888888888888888ull };
+  vector unsigned long long int source_d = { 0x8080808080808080ull,
+					     0x8080808080808080ull };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvgnb\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-7.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-7.c
new file mode 100644
index 00000000000..bbacff986a0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-7.c
@@ -0,0 +1,71 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned long long int source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned long long int source_a = { 0, 0x8888888800000000ull };
+  vector unsigned long long int source_b = { 0, 0x8080808080808080ull };
+  vector unsigned long long int source_c = { 0, 0x8888888888888888ull };
+  vector unsigned long long int source_d = { 0x8080808080808080ull,
+					     0x8080808080808080ull };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-8.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-8.c
new file mode 100644
index 00000000000..23c16e51d48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-8.c
@@ -0,0 +1,75 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned __int128 source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned __int128 source_a =
+    { ((unsigned __int128) 0x8888888800000000ull) << 64 };
+  vector unsigned __int128 source_b =
+    { ((unsigned __int128) 0x8080808080808080ull) << 64 };
+  vector unsigned __int128 source_c =
+    { ((unsigned __int128) 0x8888888888888888ull) << 64 };
+  vector unsigned __int128 source_d =
+    { 0x8080808080808080ull |
+      ((unsigned __int128) 0x8080808080808080ull) << 64 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler {\mvgnb\M} } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-gnb-9.c b/gcc/testsuite/gcc.target/powerpc/vec-gnb-9.c
new file mode 100644
index 00000000000..659e802d819
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-gnb-9.c
@@ -0,0 +1,74 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_future_hw } */
+/* { dg-options "-mdejagnu-cpu=future" } */
+
+#include <altivec.h>
+
+extern void abort (void);
+
+/* This test is replicated for every different vector type since
+   vec_gnb is polymorphic.  */
+unsigned long long int
+do_vec_gnb (vector unsigned __int128 source, int stride)
+{
+  switch (stride)
+    {
+    case 2:
+      return vec_gnb (source, 2);
+    case 3:
+      return vec_gnb (source, 3);
+    case 4:
+      return vec_gnb (source, 4);
+    case 5:
+      return vec_gnb (source, 5);
+    case 6:
+      return vec_gnb (source, 6);
+    case 7:
+      return vec_gnb (source, 7);
+
+    default:
+      /* Illegal value of stride */
+      abort ();
+      return 0;
+    }
+}
+
+int
+main (int argc, char *argv [])
+{
+  /* For result = 0xaaaa_0000_0000_0000, use:
+      stride = 2: binary 1x0x_1x0x_1x0x_... = 0x8888_8888_0000_0000, 0
+      stride = 4: binary 1xxx_0xxx_1xxx_0xxxx = 0x8080_8080_8080_8080, 0
+
+     For result = 0xaaaa_aaaa_0000_0000, use:
+      stride = 2: source = 0x8888_8888_8888_8888, 0x0 }
+      stride = 4: source = { 0x8080_8080_8080_8080, 0x8080_8080_8080_8080 }
+  */
+
+  /* The last array element appears in the left-most (first) bit
+     positions of the vector register.  */
+  vector unsigned __int128 source_a =
+    { ((unsigned __int128) 0x8888888800000000ull) << 64 };
+  vector unsigned __int128 source_b =
+    { ((unsigned __int128) 0x8080808080808080ull) << 64 };
+  vector unsigned __int128 source_c =
+    { ((unsigned __int128) 0x8888888888888888ull) << 64 };
+  vector unsigned __int128 source_d =
+    { 0x8080808080808080ull |
+      ((unsigned __int128) 0x8080808080808080ull) << 64 };
+
+  unsigned long long int results [] =
+    { 0xaaaa000000000000ull, 0xaaaa000000000000ull,
+      0xaaaaaaaa00000000ull, 0xaaaaaaaa00000000ull };
+
+  if (do_vec_gnb (source_a, 2) != results [0])
+    abort ();
+  if (do_vec_gnb (source_b, 4) != results [1])
+    abort ();
+  if (do_vec_gnb (source_c, 2) != results [2])
+    abort ();
+  if (do_vec_gnb (source_d, 4) != results [3])
+    abort ();
+
+  return 0;
+}