On 7/31/25 5:36 AM, Tejas Belagod wrote:
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 booleans.

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                             |  27 +-
  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                              |  28 +-
  .../aarch64/sve/acle/general/cops_bool.c      | 301 ++++++++++++++++++
  10 files changed, 523 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 362dc506f78..f70718a2e0a 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -1310,6 +1310,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)
@@ -1319,7 +1320,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 "
@@ -2399,6 +2401,27 @@ c_common_type_for_size (unsigned int bits, int unsignedp)
    return NULL_TREE;
  }

Missing function comment here.

+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))

It seems weird to look up normal bool and vector bool in the same function based on "precision" without reference to whether or not it's expected to be a vector. It seems like you're only using it to look up vectors, so it seems simplest to remove normal bool and call the function c_common_vector_bool_type.

But also I'm not sure why this is needed; see my comment below in cp_build_binary_op.

+       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/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 0485f695941..a2bc88bb7e2 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -22878,6 +22878,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)))

What is this for?  Are there non-standard non-vector boolean types?

+    return build1 (VIEW_CONVERT_EXPR, type, expr);
+
+  /* Use standard rules.  */
+  return NULL_TREE;
+}
+
  /* Implement TARGET_MANGLE_TYPE.  */
static const char *
diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc
index 55be12db951..b5c2e07c6f8 100644
--- a/gcc/cp/cvt.cc
+++ b/gcc/cp/cvt.cc
@@ -885,15 +885,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);

How can this happen?

+         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 a604511db71..29e1fc9fea6 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6253,18 +6253,26 @@ 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))
+           result_type = c_common_bool_type
+                           (TYPE_PRECISION (TREE_TYPE (type0)),
+                            TYPE_UNSIGNED (TREE_TYPE (type0)));

Why not result_type = boolean_type_node and fall through to build_opaque_vector_type?

Jason

Reply via email to