Support a subset of C/C++ operations (bitwise, conditional etc.) on svbool_t.

gcc/ChangeLog:

        * c-family/c-common.cc (c_build_vec_convert): Support vector boolean
        types for __builtin_convertvector ().
        (c_common_bool_type): New.  Given precision and signedness, return the
        appropriate common boolean type.
        * c-family/c-common.h (c_common_bool_type): Declare.
        * c/c-typeck.cc (build_binary_op): Support vector boolean types.
        * cp/typeck.cc (cp_build_binary_op): Likewise.
        * config/aarch64/aarch64-sve-builtins.cc (register_builtin_types): Make
        SVE vector boolean type equivalent to GNU vectors.
        * config/aarch64/aarch64-sve.md (<optab>vnx16bivnx16qi2,
        truncvnx16qivnx16bi2, vec_cmp<mode><mode>): New patterns to support
        additional operations on predicate modes.
        * config/aarch64/aarch64.cc (aarch64_valid_vector_boolean_op): New.
        (aarch64_invalid_unary_op): Consider vector bool types.
        (aarch64_invalid_binary_op): Likewise.
        (aarch64_convert_to_type): Define target hook and handle standard to
        non-standard bool conversion.
        * cp/call.cc (build_conditional_expr): Support vector booleans.
        * cp/cvt.cc (ocp_convert): Call target hook to resolve conversion
        between standard and non-standard binaries.

gcc/testsuite/ChangeLog:

        * gcc.target/aarch64/sve/acle/general/cops_bool.c: New.
---
 gcc/c-family/c-common.cc                      |  25 +-
 gcc/c-family/c-common.h                       |   1 +
 gcc/c/c-typeck.cc                             |  28 +-
 gcc/config/aarch64/aarch64-sve-builtins.cc    |   5 +-
 gcc/config/aarch64/aarch64-sve.md             |  62 ++++
 gcc/config/aarch64/aarch64.cc                 |  94 +++++-
 gcc/cp/call.cc                                |   3 +-
 gcc/cp/cvt.cc                                 |  11 +-
 gcc/cp/typeck.cc                              |  30 +-
 .../aarch64/sve/acle/general/cops_bool.c      | 300 ++++++++++++++++++
 10 files changed, 525 insertions(+), 34 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops_bool.c

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 0895c24ba97..76b54648c43 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -1309,6 +1309,7 @@ c_build_vec_convert (location_t loc1, tree expr, 
location_t loc2, tree type,
 
   if (!gnu_vector_type_p (TREE_TYPE (expr))
       || (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr))
+         && !VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (expr))
          && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (expr))))
     {
       if (complain)
@@ -1318,7 +1319,8 @@ c_build_vec_convert (location_t loc1, tree expr, 
location_t loc2, tree type,
     }
 
   if (!gnu_vector_type_p (type)
-      || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type)))
+      || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type)
+         && !VECTOR_BOOLEAN_TYPE_P (type)))
     {
       if (complain)
        error_at (loc2, "%<__builtin_convertvector%> second argument must "
@@ -2398,6 +2400,27 @@ c_common_type_for_size (unsigned int bits, int unsignedp)
   return NULL_TREE;
 }
 
+tree
+c_common_bool_type (unsigned int precision, bool unsigned_p)
+{
+  /* Standard boolean types.  */
+  if (precision == TYPE_PRECISION (boolean_type_node)
+      && unsigned_p == TYPE_UNSIGNED (boolean_type_node))
+    return boolean_type_node;
+
+  /* Non-standard boolean types created by targets.  */
+  for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t))
+    {
+      tree type = TREE_VALUE (t);
+      if (VECTOR_BOOLEAN_TYPE_P (type)
+         && precision == TYPE_PRECISION (TREE_TYPE (type))
+         && unsigned_p == TYPE_UNSIGNED (type))
+       return type;
+    }
+
+  return NULL_TREE;
+}
+
 /* Return a fixed-point type that has at least IBIT ibits and FBIT fbits
    that is unsigned if UNSIGNEDP is nonzero, otherwise signed;
    and saturating if SATP is nonzero, otherwise not saturating.  */
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 0178a106343..a2e63cf2550 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -876,6 +876,7 @@ extern bool default_handle_c_option (size_t, const char *, 
int);
 extern tree c_common_type_for_mode (machine_mode, int);
 extern tree c_common_related_vtype_for_mode (machine_mode, scalar_mode, int);
 extern tree c_common_type_for_size (unsigned int, int);
+extern tree c_common_bool_type (unsigned int, bool);
 extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
                                                int, int);
 extern tree c_common_unsigned_type (tree);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 691b583db3f..286fc6bcd02 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -14162,18 +14162,26 @@ build_binary_op (location_t location, enum tree_code 
code,
            }
 
           /* Always construct signed integer vector type.  */
-          intt = c_common_type_for_size (GET_MODE_BITSIZE
-                                        (SCALAR_TYPE_MODE
-                                         (TREE_TYPE (type0))), 0);
-         if (!intt)
+         if (VECTOR_BOOLEAN_TYPE_P (type0) && VECTOR_BOOLEAN_TYPE_P (type1))
            {
-             error_at (location, "could not find an integer type "
-                                 "of the same size as %qT",
-                       TREE_TYPE (type0));
-             return error_mark_node;
+             result_type = c_common_bool_type (TYPE_PRECISION (TREE_TYPE 
(type0)),
+                                        TYPE_UNSIGNED (TREE_TYPE (type0)));
+           }
+         else
+           {
+             intt = c_common_type_for_size (GET_MODE_BITSIZE
+                                            (SCALAR_TYPE_MODE
+                                               (TREE_TYPE (type0))), 0);
+             if (!intt)
+               {
+                 error_at (location, "could not find an integer type "
+                                     "of the same size as %qT",
+                           TREE_TYPE (type0));
+                 return error_mark_node;
+               }
+             result_type = build_opaque_vector_type
+                             (intt, TYPE_VECTOR_SUBPARTS (type0));
            }
-          result_type = build_opaque_vector_type (intt,
-                                                 TYPE_VECTOR_SUBPARTS (type0));
           converted = 1;
          ret = build_vec_cmp (resultcode, result_type, op0, op1);
          goto return_build_binary_op;
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc 
b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 5d2062726d6..640bc303f97 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -4674,9 +4674,6 @@ register_builtin_types ()
              vectype = build_truth_vector_type_for_mode (BYTES_PER_SVE_VECTOR,
                                                          VNx16BImode);
              num_pr = 1;
-             /* Leave svbool_t as indivisible for now.  We don't yet support
-                C/C++ operators on predicates.  */
-             TYPE_INDIVISIBLE_P (vectype) = 1;
            }
          else
            {
@@ -4693,12 +4690,12 @@ register_builtin_types ()
                          && TYPE_ALIGN (vectype) == 128
                          && known_eq (size, BITS_PER_SVE_VECTOR));
              num_zr = 1;
-             TYPE_INDIVISIBLE_P (vectype) = 0;
            }
          vectype = build_distinct_type_copy (vectype);
          gcc_assert (vectype == TYPE_MAIN_VARIANT (vectype));
          SET_TYPE_STRUCTURAL_EQUALITY (vectype);
          TYPE_ARTIFICIAL (vectype) = 1;
+         TYPE_INDIVISIBLE_P (vectype) = 0;
          make_type_sizeless (vectype);
        }
       if (num_pr)
diff --git a/gcc/config/aarch64/aarch64-sve.md 
b/gcc/config/aarch64/aarch64-sve.md
index a93bc463a90..c264b4b758c 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -3344,6 +3344,41 @@
   }
 )
 
+;; Unpredicated sign and zero extension from a boolean mode.
+(define_expand "<optab>vnx16bivnx16qi2"
+  [(set (match_operand:VNx16QI 0 "register_operand")
+       (unspec:VNx16QI
+         [(match_operand:VNx16BI 1 "register_operand")
+          (ANY_EXTEND:VNx16QI
+            (match_dup 2))]
+         UNSPEC_PRED_X))]
+  "TARGET_SVE"
+  {
+    emit_insn (gen_vcond_mask_vnx16qivnx16bi (operands[0],
+                                             CONSTM1_RTX (VNx16QImode),
+                                             CONST0_RTX (VNx16QImode),
+                                             operands[1]));
+    DONE;
+  }
+)
+
+;; Unpredicated truncation from QImode to boolean mode.
+(define_expand "truncvnx16qivnx16bi2"
+  [(set (match_operand:VNx16BI 0 "register_operand")
+       (unspec:VNx16BI
+         [(match_dup 2)
+          (truncate:VNx16BI
+            (match_operand:VNx16QI 1 "register_operand"))]
+         UNSPEC_PRED_X))]
+  "TARGET_SVE"
+  {
+    rtx one = CONSTM1_RTX (VNx16QImode);
+    rtx cmp = gen_rtx_EQ (VNx16QImode, operands[1], one);
+    emit_insn (gen_vec_cmpvnx16qivnx16bi (operands[0], cmp, operands[1], one));
+    DONE;
+  }
+)
+
 ;; Predicated sign and zero extension from a narrower mode.
 (define_insn "*<optab><SVE_PARTIAL_I:mode><SVE_HSDI:mode>2"
   [(set (match_operand:SVE_HSDI 0 "register_operand")
@@ -8128,6 +8163,33 @@
   }
 )
 
+(define_expand "vec_cmp<mode><mode>"
+  [(parallel
+    [(set (match_operand:PRED_ALL 0 "register_operand")
+         (match_operator:PRED_ALL 1 "aarch64_equality_operator"
+           [(match_operand:PRED_ALL 2 "register_operand")
+            (match_operand:PRED_ALL 3 "register_operand")]))])]
+  "TARGET_SVE"
+  {
+    rtx ptrue = aarch64_ptrue_reg (<MODE>mode);
+    if (GET_CODE (operands[1]) == EQ)
+      {
+        rtx tmp = gen_reg_rtx (<MODE>mode);
+       emit_insn (gen_aarch64_pred_xor<mode>_z (tmp, ptrue,
+                                                operands[2], operands[3]));
+       emit_insn (gen_aarch64_pred_xor<mode>_z (operands[0], ptrue,
+                                                tmp, ptrue));
+      }
+    else if (GET_CODE (operands[1]) == NE)
+      emit_insn (gen_aarch64_pred_xor<mode>_z (operands[0], ptrue,
+                                              operands[2], operands[3]));
+    else
+      gcc_unreachable ();
+
+    DONE;
+  }
+)
+
 ;; Unsigned integer comparisons.  Don't enforce an immediate range here, since
 ;; it depends on the comparison; leave it to aarch64_expand_sve_vec_cmp_int
 ;; instead.
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index fe76730b0a7..0fa31608f2d 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -22576,6 +22576,24 @@ aarch64_autovectorize_vector_modes (vector_modes 
*modes, bool)
   return flags;
 }
 
+/* Implement TARGET_CONVERT_TO_TYPE.  Convert EXPR to TYPE.  */
+
+static tree
+aarch64_convert_to_type (tree type, tree expr)
+{
+  /* If TYPE is a non-standard boolean type invented by the target, check if
+     EXPR can be converted to TYPE.  */
+  if (TREE_CODE (type) == BOOLEAN_TYPE
+      && TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
+      && !VECTOR_TYPE_P (type)
+      && !VECTOR_TYPE_P (TREE_TYPE (expr))
+      && TYPE_CANONICAL (type) != TYPE_CANONICAL (TREE_TYPE (expr)))
+    return build1 (VIEW_CONVERT_EXPR, type, expr);
+
+  /* Use standard rules.  */
+  return NULL_TREE;
+}
+
 /* Implement TARGET_MANGLE_TYPE.  */
 
 static const char *
@@ -29584,11 +29602,59 @@ aarch64_stack_protect_guard (void)
   return NULL_TREE;
 }
 
-/* Implement TARGET_INVALID_UNARY_OP.  */
+
+static const char *
+aarch64_valid_vector_boolean_op (int code)
+{
+  switch ((enum tree_code)code)
+    {
+    case PREINCREMENT_EXPR:
+      return N_("preincrement operation not permitted on svbool_t");
+    case PREDECREMENT_EXPR:
+      return N_("predecrement operation not permitted on svbool_t");
+    case POSTINCREMENT_EXPR:
+      return N_("postincrement operation not permitted on svbool_t");
+    case POSTDECREMENT_EXPR:
+      return N_("postdecrement operation not permitted on svbool_t");
+    case NEGATE_EXPR:
+      return N_("negation operation not permitted on svbool_t");
+    case PLUS_EXPR:
+      return N_("plus operation not permitted on svbool_t");
+    case MINUS_EXPR:
+      return N_("minus operation not permitted on svbool_t");
+    case MULT_EXPR:
+      return N_("multiply operation not permitted on svbool_t");
+    case TRUNC_DIV_EXPR:
+      return N_("divide operation not permitted on svbool_t");
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+      return N_("shift operation not permitted on svbool_t");
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+      return N_("only == and != operations permitted on svbool_t");
+    case ARRAY_REF:
+      return N_("subscript operation not supported on svbool_t");
+    default:
+      /* Operation permitted.  */
+      return NULL;
+    }
+}
+
+/* Implement TARGET_INVALID_BINARY_OP.
+   Return the diagnostic message string if the unary operation OP is
+   not permitted on TYPE, NULL otherwise.  */
 
 static const char *
 aarch64_invalid_unary_op (int op, const_tree type)
 {
+  if (VECTOR_TYPE_P (type)
+      && !TYPE_INDIVISIBLE_P (type)
+      && VECTOR_BOOLEAN_TYPE_P (type)
+      && aarch64_sve::builtin_type_p (type))
+    return aarch64_valid_vector_boolean_op (op);
+
   /* Reject all single-operand operations on __mfp8 except for &.  */
   if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node && op != ADDR_EXPR)
     return N_ ("operation not permitted on type %<mfloat8_t%>");
@@ -29597,19 +29663,29 @@ aarch64_invalid_unary_op (int op, const_tree type)
   return NULL;
 }
 
-/* Implement TARGET_INVALID_BINARY_OP.  */
+/* Implement TARGET_INVALID_BINARY_OP.
+   Return the diagnostic message string if the binary operation OP is
+   not permitted on TYPE1 and TYPE2, NULL otherwise.  */
 
 static const char *
-aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, const_tree type1,
+aarch64_invalid_binary_op (int op, const_tree type1,
                           const_tree type2)
 {
   if (VECTOR_TYPE_P (type1)
       && VECTOR_TYPE_P (type2)
       && !TYPE_INDIVISIBLE_P (type1)
-      && !TYPE_INDIVISIBLE_P (type2)
-      && (aarch64_sve::builtin_type_p (type1)
+      && !TYPE_INDIVISIBLE_P (type2))
+    {
+      if ((aarch64_sve::builtin_type_p (type1)
          != aarch64_sve::builtin_type_p (type2)))
-    return N_("cannot combine GNU and SVE vectors in a binary operation");
+       return N_("cannot combine GNU and SVE vectors in a binary operation");
+
+      if (aarch64_sve::builtin_type_p (type1)
+         && aarch64_sve::builtin_type_p (type2)
+         && VECTOR_BOOLEAN_TYPE_P (type1)
+         && VECTOR_BOOLEAN_TYPE_P (type2))
+       return aarch64_valid_vector_boolean_op (op);
+    }
 
   /* Reject all 2-operand operations on __mfp8.  */
   if (TYPE_MAIN_VARIANT (type1) == aarch64_mfp8_type_node
@@ -31551,6 +31627,9 @@ aarch64_libgcc_floating_mode_supported_p
 #undef TARGET_INVALID_BINARY_OP
 #define TARGET_INVALID_BINARY_OP aarch64_invalid_binary_op
 
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP aarch64_invalid_unary_op
+
 #undef TARGET_VERIFY_TYPE_CONTEXT
 #define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
 
@@ -31729,6 +31808,9 @@ aarch64_libgcc_floating_mode_supported_p
 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES \
   aarch64_autovectorize_vector_modes
 
+#undef TARGET_CONVERT_TO_TYPE
+#define TARGET_CONVERT_TO_TYPE aarch64_convert_to_type
+
 #undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV
 #define TARGET_ATOMIC_ASSIGN_EXPAND_FENV \
   aarch64_atomic_assign_expand_fenv
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index be9b0cf62f1..cddd45f97be 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -5841,7 +5841,8 @@ build_conditional_expr (const op_location_t &loc,
   orig_arg3 = arg3;
 
   if (gnu_vector_type_p (TREE_TYPE (arg1))
-      && VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1)))
+      && (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1))
+         || VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (arg1))))
     {
       tree arg1_type = TREE_TYPE (arg1);
 
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index bd1f147f2c5..86554cff4e3 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -872,15 +872,22 @@ ocp_convert (tree type, tree expr, int convtype, int 
flags,
          if (SCOPED_ENUM_P (intype) && (convtype & CONV_STATIC))
            e = build_nop (ENUM_UNDERLYING_TYPE (intype), e);
          if (complain & tf_warning)
-           return cp_truthvalue_conversion (e, complain);
+           e = cp_truthvalue_conversion (e, complain);
          else
            {
              /* Prevent bogus -Wint-in-bool-context warnings coming
                 from c_common_truthvalue_conversion down the line.  */
              warning_sentinel w (warn_int_in_bool_context);
              warning_sentinel c (warn_sign_compare);
-             return cp_truthvalue_conversion (e, complain);
+             e = cp_truthvalue_conversion (e, complain);
            }
+
+         /* Sometimes boolean types don't match if a non-standard boolean
+            type has been invented by the target.  */
+         tree e2 = targetm.convert_to_type (type, e);
+         if (e2)
+           return e2;
+         return e;
        }
 
       converted = convert_to_integer_maybe_fold (type, e, dofold);
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index bbaca960bd7..083e577bab4 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6201,18 +6201,28 @@ cp_build_binary_op (const op_location_t &location,
              return error_mark_node;
            }
 
-         /* Always construct signed integer vector type.  */
-         intt = c_common_type_for_size
-           (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type0))), 0);
-         if (!intt)
+         if (VECTOR_BOOLEAN_TYPE_P (type0) && VECTOR_BOOLEAN_TYPE_P (type1))
            {
-             if (complain & tf_error)
-               error_at (location, "could not find an integer type "
-                         "of the same size as %qT", TREE_TYPE (type0));
-             return error_mark_node;
+             result_type = c_common_bool_type
+                             (TYPE_PRECISION (TREE_TYPE (type0)),
+                              TYPE_UNSIGNED (TREE_TYPE (type0)));
+           }
+         else
+           {
+             /* Always construct signed integer vector type.  */
+             intt = c_common_type_for_size
+                     (GET_MODE_BITSIZE (SCALAR_TYPE_MODE (TREE_TYPE (type0)))
+                      , 0);
+             if (!intt)
+               {
+                 if (complain & tf_error)
+                   error_at (location, "could not find an integer type "
+                               "of the same size as %qT", TREE_TYPE (type0));
+                 return error_mark_node;
+               }
+             result_type = build_opaque_vector_type
+                             (intt, TYPE_VECTOR_SUBPARTS (type0));
            }
-         result_type = build_opaque_vector_type (intt,
-                                                 TYPE_VECTOR_SUBPARTS (type0));
          return build_vec_cmp (resultcode, result_type, op0, op1);
        }
       build_type = boolean_type_node;
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops_bool.c 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops_bool.c
new file mode 100644
index 00000000000..1f0b599cfbe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops_bool.c
@@ -0,0 +1,300 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+#define BOOL bool
+#else
+#define BOOL _Bool
+#endif
+
+#define DECL_FUNC_UNARY(name, op, intr, n) \
+  svbool_t __attribute__((noipa)) \
+  func_ ## name ## _unary (svbool_t a) { \
+    return op (a); \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_ ## name ## _unary () { \
+    svbool_t pg = svptrue_b8 (); \
+    svbool_t data = svptrue_pat_b8 (SV_VL ## n); \
+    svbool_t exp = intr (pg, data); \
+    svbool_t actual = func_ ## name ## _unary (data); \
+    svbool_t cmp = sveor_b_z (pg, exp, actual); \
+    if (svptest_any (pg, cmp)) \
+      __builtin_abort (); \
+  }
+
+#define DECL_FUNC_UNARY_COND(name, op, n)  \
+  svbool_t __attribute__ ((noipa)) \
+  func_ ## name  ## _unary_cond (svbool_t a) { \
+    return op (a); \
+  } \
+  svbool_t __attribute__ ((noipa)) \
+  name (svbool_t t, svbool_t a) { \
+    svbool_t pgl = sveor_b_z (t, a, svptrue_b8 ()); \
+    return pgl; \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_ ## name ## _unary_cond () { \
+    svbool_t a = svptrue_pat_b8 (SV_VL ## n); \
+    svbool_t all_true = svptrue_b8 (); \
+    svbool_t cmp = func_ ## name ## _unary_cond (a); \
+    svbool_t pgc = name (all_true, a) ; \
+    svbool_t res = sveor_b_z (all_true, cmp, pgc); \
+    if (svptest_any (all_true, res)) \
+      __builtin_abort (); \
+  }
+
+#define VECT_CST { -1, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1 }
+#define VECT_CSTN { -1, t (), 0, -1, 0, f (), 0, 0, 0, -1, 0, -1, 0, -1, 0, -1 
}
+
+#define DECL_FUNC_INIT() \
+  svbool_t __attribute__ ((noipa)) \
+  func_init1 () { \
+    svbool_t temp = VECT_CST; \
+    return temp; \
+  } \
+  svbool_t __attribute__ ((noipa)) \
+  func_init2 () { \
+    svbool_t temp = { 0 }; \
+    return temp; \
+  } \
+  svbool_t __attribute__ ((noipa)) \
+  func_init3 () { \
+    svbool_t temp = { }; \
+    return temp; \
+  } \
+  int __attribute__ ((noipa)) \
+  t () { \
+    return -1; \
+  } \
+  int __attribute__ ((noipa)) \
+  f () { \
+    return 0; \
+  } \
+  svbool_t __attribute__ ((noipa)) \
+  func_init4 () { \
+    svbool_t temp = VECT_CSTN; \
+    return temp; \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_init() { \
+    svbool_t all_true = svptrue_b8 (); \
+    svbool_t v16_true = svptrue_pat_b8 (SV_VL16); \
+    int8_t mem[] = VECT_CST; \
+    int8_t memn[] = VECT_CSTN; \
+    svint8_t t8 = svld1_s8 (v16_true, mem); \
+    svbool_t init1 = __builtin_convertvector (t8, svbool_t); \
+    svbool_t init2 = __builtin_convertvector (svindex_s8 (0, 0), svbool_t); \
+    svbool_t init3 = __builtin_convertvector (svindex_s8 (0, 0), svbool_t); \
+    svint8_t tn8 = svld1_s8 (v16_true, memn); \
+    svbool_t init4 = __builtin_convertvector (tn8, svbool_t); \
+       \
+    svbool_t res_init1 = func_init1 (); \
+    svbool_t cmp = sveor_b_z (all_true, init1, res_init1); \
+    if (svptest_any (all_true, cmp)) \
+      __builtin_abort (); \
+       \
+    svbool_t res_init2 = func_init2 (); \
+    cmp = sveor_b_z (all_true, init2, res_init2); \
+    if (svptest_any (all_true, cmp)) \
+      __builtin_abort (); \
+       \
+    svbool_t res_init3 = func_init3 (); \
+    cmp = sveor_b_z (all_true, init3, res_init3); \
+    if (svptest_any (all_true, cmp)) \
+      __builtin_abort (); \
+       \
+    svbool_t res_init4 = func_init4 (); \
+    cmp = sveor_b_z (all_true, init4, res_init4); \
+    if (svptest_any (all_true, cmp)) \
+      __builtin_abort (); \
+  }
+
+#define DECL_FUNC_BINARY(name, op, intr, n) \
+  svbool_t __attribute__((noipa)) \
+  func_ ## name ## _binary(svbool_t a, svbool_t b) { \
+    return (a) op (b); \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_ ## name ## _binary () { \
+    svbool_t pg = svptrue_b8 (); \
+    svbool_t data1 = svptrue_pat_b8 (SV_VL ## n); \
+    svbool_t data2 = svnot_b_z (pg, data1); \
+    svbool_t exp = intr (pg, data1, data2); \
+    svbool_t actual = func_ ## name ## _binary (data1, data2); \
+    svbool_t cmp = sveor_b_z (pg, exp, actual); \
+    if (svptest_any (pg, cmp)) \
+      __builtin_abort (); \
+  }
+
+#define DECL_FUNC_BINARY_COND(name, op, intr, n) \
+  svbool_t __attribute__ ((noipa)) \
+  func_ ## name ## _binary_cond(svbool_t a, svbool_t b) { \
+    return (a) op (b); \
+  } \
+  svbool_t __attribute__ ((noipa)) \
+  name ## intr (svbool_t t, svbool_t a, svbool_t b) { \
+    return sv ## intr ## _b_z (t, a, b); \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_ ## name ## _binary_cond () { \
+    svbool_t all_true = svptrue_b8 (); \
+    svbool_t a = svptrue_pat_b8 (SV_VL ## n); \
+    svbool_t b = svnot_b_z (all_true, a); \
+    svbool_t cmp = func_ ## name ## _binary_cond (a, b); \
+    svbool_t pgc = name ## intr (all_true, a, b) ; \
+    svbool_t res = sveor_b_z (all_true, cmp, pgc); \
+    if (svptest_any (all_true, res)) \
+      __builtin_abort (); \
+  }
+
+#define DECL_FUNC_BOOL_TERNARY(n) \
+  svbool_t __attribute__((noipa)) \
+  func_svbool_t_ternary_eq(svbool_t p, svbool_t q, svbool_t a, svbool_t b) { \
+    return (p == q) ? a : b; \
+  } \
+  svbool_t __attribute__((noipa)) \
+  func_svbool_t_ternary_ne(svbool_t p, svbool_t q, svbool_t a, svbool_t b) { \
+    return (p != q) ? a : b; \
+  } \
+  svbool_t __attribute__((noipa)) \
+  func_svbool_t_ternary_ex(svbool_t p, svbool_t a, svbool_t b) { \
+    return (p) ? a : b; \
+  } \
+  void __attribute__((noipa)) \
+  checkfunc_svbool_t_ternary () { \
+    svbool_t pg = svptrue_b8 (); \
+    svbool_t p = svptrue_pat_b8 (SV_VL ## n); \
+    svbool_t q = svnot_b_z (pg, p); \
+    svbool_t a = p; \
+    svbool_t b = q; \
+    svbool_t ne = sveor_b_z (pg, p, q); \
+    svbool_t eq = svnot_b_z (pg, sveor_b_z (pg, p, q)); \
+    svbool_t ex = p; \
+    svbool_t expeq = svsel_b (eq, a, b); \
+    svbool_t expne = svsel_b (ne, a, b); \
+    svbool_t expex = svsel_b (ex, a, b); \
+    svbool_t actualeq = func_svbool_t_ternary_eq (p, q, a, b); \
+    svbool_t actualne = func_svbool_t_ternary_ne (p, q, a, b); \
+    svbool_t actualex = func_svbool_t_ternary_ex (p, a, b); \
+    svbool_t pgc_eq = sveor_b_z (pg, actualeq, expeq); \
+    svbool_t pgc_ne = sveor_b_z (pg, actualne, expne); \
+    svbool_t pgc_ex = sveor_b_z (pg, actualex, expex); \
+    if (svptest_any (pg, pgc_eq)) \
+      __builtin_abort (); \
+    if (svptest_any (pg, pgc_ne)) \
+      __builtin_abort (); \
+    if (svptest_any (pg, pgc_ex)) \
+      __builtin_abort (); \
+  }
+
+svbool_t __attribute__((noipa))
+my_svneor_b_z (svbool_t pg, svbool_t a, svbool_t b)
+{
+  return svnot_b_z (pg, sveor_b_z (pg, a, b));
+}
+
+svbool_t  __attribute__((noipa))
+func_svbool_t_bc (svint8_t a)
+{
+  return __builtin_convertvector (a, svbool_t);
+}
+
+void __attribute__((noipa))
+checkfunc_svbool_t_bc ()
+{
+  svbool_t pg = svptrue_b8 ();
+  svint8_t data = { -1, -1, -1, -1 };
+  svbool_t actual = func_svbool_t_bc (data);
+  svbool_t exp = svptrue_pat_b8 (SV_VL4);
+  svbool_t cmp = sveor_b_z (pg, exp, actual);
+  if (svptest_any (pg, cmp))
+    __builtin_abort ();
+}
+
+svint8_t  __attribute__((noipa))
+func_svint8_t_bc (svbool_t a)
+{
+  return __builtin_convertvector (a, svint8_t);
+}
+
+void __attribute__((noipa))
+checkfunc_svint8_t_bc ()
+{
+  svbool_t pg = svptrue_b8 ();
+  svbool_t data = svptrue_pat_b8 (SV_VL4);
+  svint8_t actual = func_svint8_t_bc (data);
+  svint8_t exp = { -1, -1, -1, -1 };
+  svbool_t cmp = svcmpne_s8 (pg, exp, actual);
+  if (svptest_any (pg, cmp))
+    __builtin_abort ();
+}
+
+DECL_FUNC_UNARY (not, ~, svnot_b_z, 4)
+DECL_FUNC_BINARY (and, &, svand_b_z, 8)
+DECL_FUNC_BINARY (orr, |, svorr_b_z, 6)
+DECL_FUNC_BINARY (eor, ^, sveor_b_z, 3)
+
+DECL_FUNC_BINARY (eq, ==, my_svneor_b_z, 4)
+DECL_FUNC_BINARY (ne, !=, sveor_b_z, 4)
+
+DECL_FUNC_INIT ()
+
+#ifdef __cplusplus
+DECL_FUNC_UNARY_COND (lnot, !, 8)
+DECL_FUNC_BINARY_COND (and_and, &&, and, 8)
+DECL_FUNC_BINARY_COND (or_or, ||, orr, 8)
+DECL_FUNC_BOOL_TERNARY (3)
+#endif
+
+#undef DECL_FUNC_UNARY
+#define DECL_FUNC_UNARY(name, op, intr, n) \
+  checkfunc_ ## name ## _unary ();
+
+#undef DECL_FUNC_UNARY_COND
+#define DECL_FUNC_UNARY_COND(name, op, n)  \
+  checkfunc_ ## name ## _unary_cond ();
+
+#undef DECL_FUNC_INIT
+#define DECL_FUNC_INIT() \
+  checkfunc_init ();
+
+#undef DECL_FUNC_BINARY
+#define DECL_FUNC_BINARY(name, op, intr, n) \
+  checkfunc_ ## name ## _binary ();
+
+#undef DECL_FUNC_BINARY_COND
+#define DECL_FUNC_BINARY_COND(name, op, intr, n) \
+  checkfunc_ ## name ## _binary_cond ();
+
+#undef  DECL_FUNC_BOOL_TERNARY
+#define  DECL_FUNC_BOOL_TERNARY(n) \
+  checkfunc_svbool_t_ternary ();
+
+int
+main ()
+{
+  DECL_FUNC_UNARY (not, ~, svnot_b_z, 4)
+  DECL_FUNC_BINARY (and, &, svand_b_z, 8)
+  DECL_FUNC_BINARY (orr, |, svorr_b_z, 6)
+  DECL_FUNC_BINARY (eor, ^, sveor_b_z, 3)
+
+  DECL_FUNC_BINARY (ne, !=, sveor_b_z, 4)
+  DECL_FUNC_BINARY (eq, ==, my_svneor_b_z, 4)
+
+  DECL_FUNC_INIT ()
+
+  checkfunc_svbool_t_bc ();
+  checkfunc_svint8_t_bc ();
+
+#ifdef __cplusplus
+  DECL_FUNC_UNARY_COND (lnot, !, 8)
+  DECL_FUNC_BINARY_COND (and_and, &&, and, 8)
+  DECL_FUNC_BINARY_COND (or_or, ||, orr, 8)
+  DECL_FUNC_BOOL_TERNARY (3)
+#endif
+
+  return 0;
+}
-- 
2.25.1


Reply via email to