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