On 27/08/2025 15:42, Jason Merrill wrote:
On 8/27/25 6:36 AM, Tejas Belagod wrote:
+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?
Hi Jason, thanks for the comments. Sorry for the delayed reply - I was
on holiday.
I'll try to summarize the answer to your questions about non-standard
boolean types. The non-standard bool types are now created by the
aarch64 backend for the SVE ACLE vector boolean type svbool_t using a
combination of build_truth_vector_type_for_mode () and
build_nonstandard_boolean_type () in tree.cc. Here the scalar
counterpart is created as signed whereas the standard
boolean_type_node is unsigned. This is the reason I have to do an
extra conversion step in ocp_convert () if I see a scalar type that is
a target's truth type for eg.
Makes sense, though how do we get a scalar expression of that type?
I think I ran into an ICE when processing init constructors for
vector-bools which is probably where extraction of the vector-bool to
the scalar type happened.
Also, I have a follow-up patch that supports the index operator for
vector-bools, so something like
bool foo (svbool_t p) { return p[5]; }
this extracts the scalar type out of the bool-vector.
I'm not too sure what caused the ICE (init or the index operator) - I'll
get back to you on the respin - if init didn't need this fix, I can move
the ocp_convert () change to the index operator patch.
>
Re your comments on cp_build_binary_op (), I end up building a binary
operator tree for vector booleans based on what the scalar
counterparts correspond to which could be a standard or non-standard
bool type (aka unsigned vs signed). I see your point about making it a
vector-specific type-lookup function as I currently only use it for a
vector-vector binary op - I will fix that - thanks for spotting that.
In addition, I don't fall-through to build_opaque_vector_type as I
directly return the vector type from c_common_bool_type () and also
boolean_type_node is different from non-standard bool type due to the
signedness explained above. I could change this to make
c_common_bool_type () return a scalar boolean type and then fall-
through to build_opaque_vector_type (), but will it build me the same
type as expected for a svbool_t vector boolean type? I wasn't very
sure if that would work, so I took the approach to directly return the
type that's been registered by the backend.
In general, I can't seem to assume the standard boolean_type_node for
the scalar counterpart of vector boolean types as vector booleans
currently only seem to be created by targets (eg. we don't allow
defintions like typedef bool v16bi __attribute__((vector_size (2))); )
and this means it could have any precision as defined by the target
which could be different from the standard boolean_type_node.
Fair enough. Though if you already have bool-vector types in the
arguments, can't you use one of those types directly instead of looking
up a type with the same qualities?
I hadn't thought of that - let me try it, thanks!
Tejas.
Jason