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