vector_types_convertible_p rejects conversions between fixed-length and
scalable vector types when their TYPE_SIZEs are not comparable.

TARGET_CONVERT_TO_TYPE cannot handle this because convert_for_assignment
checks type compatibility before performing conversions.

Add TARGET_VECTOR_TYPES_CONVERTIBLE_P so targets can accept such
conversions.  It defaults to false; the RISC-V port later in this series is
the first to define it, and brings the tests.

gcc/
        * target.def (vector_types_convertible_p): New hook.
        * doc/tm.texi.in: Add TARGET_VECTOR_TYPES_CONVERTIBLE_P.
        * doc/tm.texi: Regenerate.
        * hooks.cc (hook_bool_const_tree_const_tree_false): New.
        * hooks.h (hook_bool_const_tree_const_tree_false): Declare.

gcc/c-family/
        * c-common.cc (vector_types_convertible_p): Return true if
        targetm.vector_types_convertible_p accepts the pair.
---
 gcc/c-family/c-common.cc |  3 +++
 gcc/doc/tm.texi          | 11 +++++++++++
 gcc/doc/tm.texi.in       |  2 ++
 gcc/hooks.cc             |  7 +++++++
 gcc/hooks.h              |  1 +
 gcc/target.def           | 14 ++++++++++++++
 6 files changed, 38 insertions(+)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 6380bec4515..3e993f25cd9 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -1041,6 +1041,9 @@ vector_types_convertible_p (const_tree t1, const_tree t2, 
bool emit_lax_note)
      && (INTEGRAL_TYPE_P (TREE_TYPE (t1))
         == INTEGRAL_TYPE_P (TREE_TYPE (t2))));
 
+  if (targetm.vector_types_convertible_p (t1, t2))
+    return true;
+
   if (!convertible_lax || flag_lax_vector_conversions)
     return convertible_lax;
 
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 97afd017522..7b44556c0e8 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -12780,6 +12780,17 @@ and @var{type2}, or @code{NULL} if validity should be 
determined by
 the front end.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_VECTOR_TYPES_CONVERTIBLE_P (const_tree 
@var{type1}, const_tree @var{type2})
+This hook returns true if the vector types @var{type1} and @var{type2}
+can be converted into each other.  It is consulted before the size-based
+rules, which cannot judge a pair whose sizes are not comparable.  This
+hook is useful when there are target-specific vector types with special
+conversion rules, such as a fixed-length type that describes a prefix of
+a variable-length vector.  A target that defines it will normally define
+@code{TARGET_CONVERT_TO_TYPE} too.
+This is currently used only by the C and C++ front ends.
+@end deftypefn
+
 @deftypefn {Target Hook} tree TARGET_PROMOTED_TYPE (const_tree @var{type})
 If defined, this target hook returns the type to which values of
 @var{type} should be promoted when they appear in expressions,
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 2113b9c679a..3391fd6e860 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -8094,6 +8094,8 @@ and scanf formatter settings.
 
 @hook TARGET_INVALID_BINARY_OP
 
+@hook TARGET_VECTOR_TYPES_CONVERTIBLE_P
+
 @hook TARGET_PROMOTED_TYPE
 
 @hook TARGET_CONVERT_TO_TYPE
diff --git a/gcc/hooks.cc b/gcc/hooks.cc
index 2b47fd3e50f..1b99cf2035b 100644
--- a/gcc/hooks.cc
+++ b/gcc/hooks.cc
@@ -334,6 +334,13 @@ hook_bool_const_tree_const_tree_true (const_tree, 
const_tree)
   return true;
 }
 
+/* Generic hook that takes (const_tree, const_tree) and returns false.  */
+bool
+hook_bool_const_tree_const_tree_false (const_tree, const_tree)
+{
+  return false;
+}
+
 bool
 hook_bool_tree_true (tree)
 {
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 1ad4abb5500..1fa173f1c74 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -50,6 +50,7 @@ extern bool hook_bool_uint_mode_true (unsigned int, 
machine_mode);
 extern bool hook_bool_tree_false (tree);
 extern bool hook_bool_const_tree_false (const_tree);
 extern bool hook_bool_const_tree_const_tree_true (const_tree, const_tree);
+extern bool hook_bool_const_tree_const_tree_false (const_tree, const_tree);
 extern bool hook_bool_tree_true (tree);
 extern bool hook_bool_const_tree_true (const_tree);
 extern bool hook_bool_gsiptr_false (gimple_stmt_iterator *);
diff --git a/gcc/target.def b/gcc/target.def
index 11334f9d443..e7e76e42377 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -5788,6 +5788,20 @@ the front end.",
  const char *, (int op, const_tree type1, const_tree type2),
  hook_constcharptr_int_const_tree_const_tree_null)
 
+/* Return true if TYPE1 and TYPE2 convert via a target-specific rule.  */
+DEFHOOK
+(vector_types_convertible_p,
+ "This hook returns true if the vector types @var{type1} and @var{type2}\n\
+can be converted into each other.  It is consulted before the size-based\n\
+rules, which cannot judge a pair whose sizes are not comparable.  This\n\
+hook is useful when there are target-specific vector types with special\n\
+conversion rules, such as a fixed-length type that describes a prefix of\n\
+a variable-length vector.  A target that defines it will normally define\n\
+@code{TARGET_CONVERT_TO_TYPE} too.\n\
+This is currently used only by the C and C++ front ends.",
+ bool, (const_tree type1, const_tree type2),
+ hook_bool_const_tree_const_tree_false)
+
 /* If values of TYPE are promoted to some other type when used in
    expressions (analogous to the integer promotions), return that type,
    or NULL_TREE otherwise.  */
-- 
2.54.0

Reply via email to