CellSPU:
- Fix bugs 3194, 3195: i128 load/stores produce correct code (although, we
  need to ensure that i128 is 16-byte aligned in real life), and 128 zero-
  extends are supported.
- New td file: SPU128InstrInfo.td: this is where all new i128 support should
  be put in the future.
- Continue to hammer on i64 operations and test cases; ensure that the only
  remaining problem will be i64 mul.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61784 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CodeGen/CellSPU/i64ops.ll b/test/CodeGen/CellSPU/i64ops.ll
index 51abd44..d118c5f 100644
--- a/test/CodeGen/CellSPU/i64ops.ll
+++ b/test/CodeGen/CellSPU/i64ops.ll
@@ -1,6 +1,8 @@
 ; RUN: llvm-as -o - %s | llc -march=cellspu > %t1.s
-; RUN: grep xswd	     %t1.s | count 1
-; RUN: grep shufb            %t1.s | count 2
+; RUN: grep xswd	     %t1.s | count 3
+; RUN: grep xsbh	     %t1.s | count 1
+; RUN: grep xshw	     %t1.s | count 2
+; RUN: grep shufb            %t1.s | count 4
 ; RUN: grep cg               %t1.s | count 1
 ; RUN: grep addx             %t1.s | count 1
 
@@ -8,11 +10,31 @@
 target datalayout = "E-p:32:32:128-f64:64:128-f32:32:128-i64:32:128-i32:32:128-i16:16:128-i8:8:128-i1:8:128-a0:0:128-v128:128:128-s0:128:128"
 target triple = "spu"
 
+define i64 @sext_i64_i8(i8 %a) nounwind {
+  %1 = sext i8 %a to i64
+  ret i64 %1
+}
+
+define i64 @sext_i64_i16(i16 %a) nounwind {
+  %1 = sext i16 %a to i64
+  ret i64 %1
+}
+
 define i64 @sext_i64_i32(i32 %a) nounwind {
   %1 = sext i32 %a to i64
   ret i64 %1
 }
 
+define i64 @zext_i64_i8(i8 %a) nounwind {
+  %1 = zext i8 %a to i64
+  ret i64 %1
+}
+
+define i64 @zext_i64_i16(i16 %a) nounwind {
+  %1 = zext i16 %a to i64
+  ret i64 %1
+}
+
 define i64 @zext_i64_i32(i32 %a) nounwind {
   %1 = zext i32 %a to i64
   ret i64 %1
diff --git a/test/CodeGen/CellSPU/useful-harnesses/i64operations.c b/test/CodeGen/CellSPU/useful-harnesses/i64operations.c
index b93ce37..7a4bf1a 100644
--- a/test/CodeGen/CellSPU/useful-harnesses/i64operations.c
+++ b/test/CodeGen/CellSPU/useful-harnesses/i64operations.c
@@ -1,20 +1,12 @@
 #include <stdio.h>
-
-#define TRUE_VAL (!0)
-#define FALSE_VAL 0
-#define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
-
-typedef unsigned long long int uint64_t;
-typedef long long int int64_t;
-
-/* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
+#include "i64operations.h"
 
 int64_t         tval_a = 1234567890003LL;
 int64_t         tval_b = 2345678901235LL;
 int64_t         tval_c = 1234567890001LL;
 int64_t         tval_d = 10001LL;
 int64_t         tval_e = 10000LL;
-int64_t         tval_f = -1068103409991LL;
+uint64_t        tval_f = 0xffffff0750135eb9;
 
 /* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
 
@@ -132,44 +124,6 @@
 
 /* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
 
-struct harness_int64_pred {
-  const char     *fmt_string;
-  int64_t        *lhs;
-  int64_t        *rhs;
-  int64_t        *select_a;
-  int64_t        *select_b;
-  int             expected;
-  int64_t        *select_expected;
-};
-
-struct harness_uint64_pred {
-  const char     *fmt_string;
-  uint64_t       *lhs;
-  uint64_t       *rhs;
-  uint64_t       *select_a;
-  uint64_t       *select_b;
-  int             expected;
-  uint64_t       *select_expected;
-};
-
-struct int64_pred_s {
-  const char     *name;
-  int             (*predfunc) (int64_t, int64_t);
-  int64_t         (*selfunc) (int64_t, int64_t, int64_t, int64_t);
-  struct harness_int64_pred *tests;
-  int             n_tests;
-};
-
-struct uint64_pred_s {
-  const char     *name;
-  int             (*predfunc) (uint64_t, uint64_t);
-  uint64_t        (*selfunc) (uint64_t, uint64_t, uint64_t, uint64_t);
-  struct harness_uint64_pred *tests;
-  int             n_tests;
-};
-
-/* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
-
 struct harness_int64_pred int64_tests_eq[] = {
   {"a %s a", &tval_a, &tval_a, &tval_c, &tval_d, TRUE_VAL, &tval_c},
   {"a %s b", &tval_a, &tval_b, &tval_c, &tval_d, FALSE_VAL, &tval_d},
@@ -304,8 +258,9 @@
   int             j, failed = 0;
 
   for (j = 0; j < pred->n_tests; ++j) {
-    int             pred_result =
-    (*pred->predfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs);
+    int             pred_result;
+
+    pred_result = (*pred->predfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs);
 
     if (pred_result != pred->tests[j].expected) {
       char            str[64];
@@ -313,27 +268,39 @@
       sprintf(str, pred->tests[j].fmt_string, pred->name);
       printf("%s: returned value is %d, expecting %d\n", str,
 	     pred_result, pred->tests[j].expected);
-      printf("  lhs = %19lld (0x%016llx)\n", *pred->tests[j].lhs, *pred->tests[j].lhs);
-      printf("  rhs = %19lld (0x%016llx)\n", *pred->tests[j].rhs, *pred->tests[j].rhs);
+      printf("  lhs = %19lld (0x%016llx)\n", *pred->tests[j].lhs,
+             *pred->tests[j].lhs);
+      printf("  rhs = %19lld (0x%016llx)\n", *pred->tests[j].rhs,
+             *pred->tests[j].rhs);
       ++failed;
     } else {
-      int64_t         selresult = (pred->selfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs,
-			  *pred->tests[j].select_a, *pred->tests[j].select_b);
+      int64_t         selresult;
+
+      selresult = (pred->selfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs,
+                                   *pred->tests[j].select_a,
+                                   *pred->tests[j].select_b);
+
       if (selresult != *pred->tests[j].select_expected) {
 	char            str[64];
 
 	sprintf(str, pred->tests[j].fmt_string, pred->name);
 	printf("%s select: returned value is %d, expecting %d\n", str,
 	       pred_result, pred->tests[j].expected);
-	printf("  lhs   = %19lld (0x%016llx)\n", *pred->tests[j].lhs, *pred->tests[j].lhs);
-	printf("  rhs   = %19lld (0x%016llx)\n", *pred->tests[j].rhs, *pred->tests[j].rhs);
-	printf("  true  = %19lld (0x%016llx)\n", *pred->tests[j].select_a, *pred->tests[j].select_a);
-	printf("  false = %19lld (0x%016llx)\n", *pred->tests[j].select_b, *pred->tests[j].select_b);
+	printf("  lhs   = %19lld (0x%016llx)\n", *pred->tests[j].lhs,
+	       *pred->tests[j].lhs);
+	printf("  rhs   = %19lld (0x%016llx)\n", *pred->tests[j].rhs,
+	       *pred->tests[j].rhs);
+	printf("  true  = %19lld (0x%016llx)\n", *pred->tests[j].select_a,
+	       *pred->tests[j].select_a);
+	printf("  false = %19lld (0x%016llx)\n", *pred->tests[j].select_b,
+	       *pred->tests[j].select_b);
 	++failed;
       }
     }
   }
 
+  printf("  %d tests performed, should be %d.\n", j, pred->n_tests);
+
   return failed;
 }
 
@@ -343,77 +310,240 @@
   int             j, failed = 0;
 
   for (j = 0; j < pred->n_tests; ++j) {
-    int             pred_result = (*pred->predfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs);
+    int             pred_result;
 
+    pred_result = (*pred->predfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs);
     if (pred_result != pred->tests[j].expected) {
       char            str[64];
 
       sprintf(str, pred->tests[j].fmt_string, pred->name);
       printf("%s: returned value is %d, expecting %d\n", str,
 	     pred_result, pred->tests[j].expected);
-      printf("  lhs = %19llu (0x%016llx)\n", *pred->tests[j].lhs, *pred->tests[j].lhs);
-      printf("  rhs = %19llu (0x%016llx)\n", *pred->tests[j].rhs, *pred->tests[j].rhs);
+      printf("  lhs = %19llu (0x%016llx)\n", *pred->tests[j].lhs,
+             *pred->tests[j].lhs);
+      printf("  rhs = %19llu (0x%016llx)\n", *pred->tests[j].rhs,
+             *pred->tests[j].rhs);
       ++failed;
     } else {
-      uint64_t        selresult = (pred->selfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs,
-			  *pred->tests[j].select_a, *pred->tests[j].select_b);
+      uint64_t        selresult;
+
+      selresult = (pred->selfunc) (*pred->tests[j].lhs, *pred->tests[j].rhs,
+                                   *pred->tests[j].select_a,
+                                   *pred->tests[j].select_b);
       if (selresult != *pred->tests[j].select_expected) {
 	char            str[64];
 
 	sprintf(str, pred->tests[j].fmt_string, pred->name);
 	printf("%s select: returned value is %d, expecting %d\n", str,
 	       pred_result, pred->tests[j].expected);
-	printf("  lhs   = %19llu (0x%016llx)\n", *pred->tests[j].lhs, *pred->tests[j].lhs);
-	printf("  rhs   = %19llu (0x%016llx)\n", *pred->tests[j].rhs, *pred->tests[j].rhs);
-	printf("  true  = %19llu (0x%016llx)\n", *pred->tests[j].select_a, *pred->tests[j].select_a);
-	printf("  false = %19llu (0x%016llx)\n", *pred->tests[j].select_b, *pred->tests[j].select_b);
+	printf("  lhs   = %19llu (0x%016llx)\n", *pred->tests[j].lhs,
+	       *pred->tests[j].lhs);
+	printf("  rhs   = %19llu (0x%016llx)\n", *pred->tests[j].rhs,
+	       *pred->tests[j].rhs);
+	printf("  true  = %19llu (0x%016llx)\n", *pred->tests[j].select_a,
+	       *pred->tests[j].select_a);
+	printf("  false = %19llu (0x%016llx)\n", *pred->tests[j].select_b,
+	       *pred->tests[j].select_b);
 	++failed;
       }
     }
-
   }
 
+  printf("  %d tests performed, should be %d.\n", j, pred->n_tests);
+
   return failed;
 }
 
 /* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
 
-uint64_t
-i64_shl_const(uint64_t a)
-{
+int
+test_i64_sext_i32(int in, int64_t expected) {
+  int64_t result = (int64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_sext_i32(%d) returns %lld\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_sext_i16(short in, int64_t expected) {
+  int64_t result = (int64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_sext_i16(%hd) returns %lld\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_sext_i8(signed char in, int64_t expected) {
+  int64_t result = (int64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_sext_i8(%d) returns %lld\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_zext_i32(unsigned int in, uint64_t expected) {
+  uint64_t result = (uint64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_zext_i32(%u) returns %llu\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_zext_i16(unsigned short in, uint64_t expected) {
+  uint64_t result = (uint64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_zext_i16(%hu) returns %llu\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_zext_i8(unsigned char in, uint64_t expected) {
+  uint64_t result = (uint64_t) in;
+
+  if (result != expected) {
+    char str[64];
+    sprintf(str, "i64_zext_i8(%u) returns %llu\n", in, result);
+    return 1;
+  }
+
+  return 0;
+}
+
+/* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
+
+int64_t
+i64_shl_const(int64_t a) {
   return a << 10;
 }
 
-uint64_t
-i64_shl(uint64_t a, int amt)
-{
+int64_t
+i64_shl(int64_t a, int amt) {
   return a << amt;
 }
 
 uint64_t
-i64_srl_const(uint64_t a)
-{
+u64_shl_const(uint64_t a) {
+  return a << 10;
+}
+
+uint64_t
+u64_shl(uint64_t a, int amt) {
+  return a << amt;
+}
+
+int64_t
+i64_srl_const(int64_t a) {
+  return a >> 10;
+}
+
+int64_t
+i64_srl(int64_t a, int amt) {
+  return a >> amt;
+}
+
+uint64_t
+u64_srl_const(uint64_t a) {
   return a >> 10;
 }
 
 uint64_t
-i64_srl(uint64_t a, int amt)
-{
+u64_srl(uint64_t a, int amt) {
   return a >> amt;
 }
 
 int64_t
-i64_sra_const(int64_t a)
-{
+i64_sra_const(int64_t a) {
   return a >> 10;
 }
 
 int64_t
-i64_sra(int64_t a, int amt)
-{
+i64_sra(int64_t a, int amt) {
   return a >> amt;
 }
 
+uint64_t
+u64_sra_const(uint64_t a) {
+  return a >> 10;
+}
+
+uint64_t
+u64_sra(uint64_t a, int amt) {
+  return a >> amt;
+}
+
+int
+test_u64_constant_shift(const char *func_name, uint64_t (*func)(uint64_t), uint64_t a, uint64_t expected) {
+  uint64_t result = (*func)(a);
+
+  if (result != expected) {
+    printf("%s(0x%016llx) returns 0x%016llx, expected 0x%016llx\n", func_name, a, result, expected);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_constant_shift(const char *func_name, int64_t (*func)(int64_t), int64_t a, int64_t expected) {
+  int64_t result = (*func)(a);
+
+  if (result != expected) {
+    printf("%s(0x%016llx) returns 0x%016llx, expected 0x%016llx\n", func_name, a, result, expected);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_u64_variable_shift(const char *func_name, uint64_t (*func)(uint64_t, int), uint64_t a, unsigned int b, uint64_t expected) {
+  uint64_t result = (*func)(a, b);
+
+  if (result != expected) {
+    printf("%s(0x%016llx, %d) returns 0x%016llx, expected 0x%016llx\n", func_name, a, b, result, expected);
+    return 1;
+  }
+
+  return 0;
+}
+
+int
+test_i64_variable_shift(const char *func_name, int64_t (*func)(int64_t, int), int64_t a, unsigned int b, int64_t expected) {
+  int64_t result = (*func)(a, b);
+
+  if (result != expected) {
+    printf("%s(0x%016llx, %d) returns 0x%016llx, expected 0x%016llx\n", func_name, a, b, result, expected);
+    return 1;
+  }
+
+  return 0;
+}
+
 /* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
 
 int
@@ -423,12 +553,12 @@
   const char     *something_failed = "  %d tests failed.\n";
   const char     *all_tests_passed = "  All tests passed.\n";
 
-  printf("a = %16lld (0x%016llx)\n", tval_a, tval_a);
-  printf("b = %16lld (0x%016llx)\n", tval_b, tval_b);
-  printf("c = %16lld (0x%016llx)\n", tval_c, tval_c);
-  printf("d = %16lld (0x%016llx)\n", tval_d, tval_d);
-  printf("e = %16lld (0x%016llx)\n", tval_e, tval_e);
-  printf("f = %16lld (0x%016llx)\n", tval_f, tval_f);
+  printf("tval_a = %20lld (0x%020llx)\n", tval_a, tval_a);
+  printf("tval_b = %20lld (0x%020llx)\n", tval_b, tval_b);
+  printf("tval_c = %20lld (0x%020llx)\n", tval_c, tval_c);
+  printf("tval_d = %20lld (0x%020llx)\n", tval_d, tval_d);
+  printf("tval_e = %20lld (0x%020llx)\n", tval_e, tval_e);
+  printf("tval_f = %20llu (0x%020llx)\n", tval_f, tval_f);
   printf("----------------------------------------\n");
 
   for (i = 0; i < ARR_SIZE(int64_preds); ++i) {
@@ -453,22 +583,70 @@
     printf("----------------------------------------\n");
   }
 
-  printf("a                = 0x%016llx\n", tval_a);
-  printf("i64_shl_const(a) = 0x%016llx\n", i64_shl_const(tval_a));
-  printf("i64_shl(a)       = 0x%016llx\n", i64_shl(tval_a, 10));
-  printf("i64_srl_const(a) = 0x%016llx\n", i64_srl_const(tval_a));
-  printf("i64_srl(a)       = 0x%016llx\n", i64_srl(tval_a, 10));
-  printf("i64_sra_const(a) = 0x%016llx\n", i64_sra_const(tval_a));
-  printf("i64_sra(a)       = 0x%016llx\n", i64_sra(tval_a, 10));
+  /*----------------------------------------------------------------------*/
+
+  puts("signed/zero-extend tests:");
+
+  failed = 0;
+  failed += test_i64_sext_i32(-1, -1LL);
+  failed += test_i64_sext_i32(10, 10LL);
+  failed += test_i64_sext_i32(0x7fffffff, 0x7fffffffLL);
+  failed += test_i64_sext_i16(-1, -1LL);
+  failed += test_i64_sext_i16(10, 10LL);
+  failed += test_i64_sext_i16(0x7fff, 0x7fffLL);
+  failed += test_i64_sext_i8(-1, -1LL);
+  failed += test_i64_sext_i8(10, 10LL);
+  failed += test_i64_sext_i8(0x7f, 0x7fLL);
+
+  failed += test_i64_zext_i32(0xffffffff, 0x00000000ffffffffLLU);
+  failed += test_i64_zext_i32(0x01234567, 0x0000000001234567LLU);
+  failed += test_i64_zext_i16(0xffff,     0x000000000000ffffLLU);
+  failed += test_i64_zext_i16(0x569a,     0x000000000000569aLLU);
+  failed += test_i64_zext_i8(0xff,        0x00000000000000ffLLU);
+  failed += test_i64_zext_i8(0xa0,        0x00000000000000a0LLU);
+
+  if (failed > 0) {
+    printf("  %d tests failed.\n", failed);
+  } else {
+    printf("  All tests passed.\n");
+  }
+
   printf("----------------------------------------\n");
 
-  printf("f                = 0x%016llx\n", tval_f);
-  printf("i64_shl_const(f) = 0x%016llx\n", i64_shl_const(tval_f));
-  printf("i64_shl(f)       = 0x%016llx\n", i64_shl(tval_f, 10));
-  printf("i64_srl_const(f) = 0x%016llx\n", i64_srl_const(tval_f));
-  printf("i64_srl(f)       = 0x%016llx\n", i64_srl(tval_f, 10));
-  printf("i64_sra_const(f) = 0x%016llx\n", i64_sra_const(tval_f));
-  printf("i64_sra(f)       = 0x%016llx\n", i64_sra(tval_f, 10));
+  failed = 0;
+  puts("signed left/right shift tests:");
+  failed += test_i64_constant_shift("i64_shl_const", i64_shl_const, tval_a,     0x00047dc7ec114c00LL);
+  failed += test_i64_variable_shift("i64_shl",       i64_shl,       tval_a, 10, 0x00047dc7ec114c00LL);
+  failed += test_i64_constant_shift("i64_srl_const", i64_srl_const, tval_a,     0x0000000047dc7ec1LL);
+  failed += test_i64_variable_shift("i64_srl",       i64_srl,       tval_a, 10, 0x0000000047dc7ec1LL);
+  failed += test_i64_constant_shift("i64_sra_const", i64_sra_const, tval_a,     0x0000000047dc7ec1LL);
+  failed += test_i64_variable_shift("i64_sra",       i64_sra,       tval_a, 10, 0x0000000047dc7ec1LL);
+
+  if (failed > 0) {
+    printf("  %d tests ailed.\n", failed);
+  } else {
+    printf("  All tests passed.\n");
+  }
+
+  printf("----------------------------------------\n");
+
+  failed = 0;
+  puts("unsigned left/right shift tests:");
+  failed += test_u64_constant_shift("u64_shl_const", u64_shl_const,  tval_f,     0xfffc1d404d7ae400LL);
+  failed += test_u64_variable_shift("u64_shl",       u64_shl,        tval_f, 10, 0xfffc1d404d7ae400LL);
+  failed += test_u64_constant_shift("u64_srl_const", u64_srl_const,  tval_f,     0x003fffffc1d404d7LL);
+  failed += test_u64_variable_shift("u64_srl",       u64_srl,        tval_f, 10, 0x003fffffc1d404d7LL);
+  failed += test_i64_constant_shift("i64_sra_const", i64_sra_const,  tval_f,     0xffffffffc1d404d7LL);
+  failed += test_i64_variable_shift("i64_sra",       i64_sra,        tval_f, 10, 0xffffffffc1d404d7LL);
+  failed += test_u64_constant_shift("u64_sra_const", u64_sra_const,  tval_f,     0x003fffffc1d404d7LL);
+  failed += test_u64_variable_shift("u64_sra",       u64_sra,        tval_f, 10, 0x003fffffc1d404d7LL);
+
+  if (failed > 0) {
+    printf("  %d tests ailed.\n", failed);
+  } else {
+    printf("  All tests passed.\n");
+  }
+
   printf("----------------------------------------\n");
 
   return 0;
diff --git a/test/CodeGen/CellSPU/useful-harnesses/i64operations.h b/test/CodeGen/CellSPU/useful-harnesses/i64operations.h
new file mode 100644
index 0000000..7a02794
--- /dev/null
+++ b/test/CodeGen/CellSPU/useful-harnesses/i64operations.h
@@ -0,0 +1,43 @@
+#define TRUE_VAL (!0)
+#define FALSE_VAL 0
+#define ARR_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
+typedef unsigned long long int uint64_t;
+typedef long long int int64_t;
+
+/* ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~- */
+struct harness_int64_pred {
+  const char     *fmt_string;
+  int64_t        *lhs;
+  int64_t        *rhs;
+  int64_t        *select_a;
+  int64_t        *select_b;
+  int             expected;
+  int64_t        *select_expected;
+};
+
+struct harness_uint64_pred {
+  const char     *fmt_string;
+  uint64_t       *lhs;
+  uint64_t       *rhs;
+  uint64_t       *select_a;
+  uint64_t       *select_b;
+  int             expected;
+  uint64_t       *select_expected;
+};
+
+struct int64_pred_s {
+  const char     *name;
+  int             (*predfunc) (int64_t, int64_t);
+  int64_t         (*selfunc) (int64_t, int64_t, int64_t, int64_t);
+  struct harness_int64_pred *tests;
+  int             n_tests;
+};
+
+struct uint64_pred_s {
+  const char     *name;
+  int             (*predfunc) (uint64_t, uint64_t);
+  uint64_t        (*selfunc) (uint64_t, uint64_t, uint64_t, uint64_t);
+  struct harness_uint64_pred *tests;
+  int             n_tests;
+};