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


Reply via email to