Hi,
The same handling for nop conversions we did in the !maybe_ident case is
also necessary in for maybe_ident. This patch performs the necessary
preprocessing before the if and unifies the nop-conversion handling.
I'm not so happy with how all these patches trickled down one by one
but I'm going to blame it partially on the lack of test coverage and
the opaque code in simplify_vector_constructor. The rest is on me.
And test coverage has definitely improved now :)
Bootstrapped and regtested on x86, power10, and aarch64.
Regtested on riscv64.
Regards
Robin
PR tree-optimization/123925
gcc/ChangeLog:
* tree-ssa-forwprop.cc (simplify_vector_constructor):
Add nop-conversion handling for maybe_ident.
gcc/testsuite/ChangeLog:
* gcc.target/riscv/rvv/autovec/pr123925.c: New test.
---
.../gcc.target/riscv/rvv/autovec/pr123925.c | 28 ++++++++++
gcc/tree-ssa-forwprop.cc | 55 +++++++++++--------
2 files changed, 60 insertions(+), 23 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123925.c
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123925.c
b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123925.c
new file mode 100644
index 00000000000..c209387531c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr123925.c
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-require-effective-target riscv_v_ok } */
+/* { dg-add-options riscv_v } */
+/* { dg-additional-options "-std=gnu99" } */
+
+typedef __attribute__((__vector_size__ (8))) unsigned char U;
+typedef __attribute__((__vector_size__ (8))) signed long V;
+
+signed char s;
+V v;
+
+void
+__attribute__ ((noipa))
+foo (U u, V *r)
+{
+ __builtin_memmove (&s, &u, 1);
+ v += s;
+ *r = v;
+}
+
+int
+main ()
+{
+ V x;
+ foo ((U) {248}, &x);
+ if (x[0] != -8)
+ __builtin_abort();
+}
diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index cea5e70dd75..74e2875d769 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -3975,14 +3975,29 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
if (refnelts < nelts)
return false;
+ /* Determine the element type for the conversion source.
+ As orig_elem_type keeps track of the original type, check
+ if we need to perform a sign swap after permuting.
+ We need to be able to construct a vector type from the element
+ type which is not possible for e.g. BitInt or pointers
+ so pun with an integer type if needed. */
+ tree perm_eltype = TREE_TYPE (TREE_TYPE (orig[0]));
+ bool sign_change_p = false;
+ if (conv_code != ERROR_MARK
+ && orig_elem_type[0]
+ && TYPE_SIGN (orig_elem_type[0]) != TYPE_SIGN (perm_eltype))
+ {
+ perm_eltype = signed_or_unsigned_type_for
+ (TYPE_UNSIGNED (orig_elem_type[0]), perm_eltype);
+ sign_change_p = true;
+ }
+ tree conv_src_type = build_vector_type (perm_eltype, nelts);
+
if (maybe_ident)
{
- tree conv_src_type
- = (nelts != refnelts
- ? (conv_code != ERROR_MARK
- ? build_vector_type (TREE_TYPE (TREE_TYPE (orig[0])), nelts)
- : type)
- : TREE_TYPE (orig[0]));
+ /* When there is no conversion, use the target type directly. */
+ if (conv_code == ERROR_MARK && nelts != refnelts)
+ conv_src_type = type;
if (conv_code != ERROR_MARK
&& !supportable_convert_operation (conv_code, type, conv_src_type,
&conv_code))
@@ -4104,6 +4119,15 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
gsi_insert_before (gsi, lowpart, GSI_SAME_STMT);
orig[0] = gimple_assign_lhs (lowpart);
}
+ else if (sign_change_p)
+ {
+ gassign *conv
+ = gimple_build_assign (make_ssa_name (conv_src_type),
+ build1 (VIEW_CONVERT_EXPR, conv_src_type,
+ orig[0]));
+ gsi_insert_before (gsi, conv, GSI_SAME_STMT);
+ orig[0] = gimple_assign_lhs (conv);
+ }
if (conv_code == ERROR_MARK)
{
tree src_type = TREE_TYPE (orig[0]);
@@ -4135,22 +4159,8 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
&& orig[1] == error_mark_node
&& !maybe_blend[0])
return false;
- tree mask_type, perm_type, conv_src_type;
+ tree mask_type, perm_type;
perm_type = TREE_TYPE (orig[0]);
- /* Determine the element type for the conversion source.
- As orig_elem_type keeps track of the original type, check
- if we need to perform a sign swap after permuting.
- We need to be able to construct a vector type from the element
- type which is not possible for e.g. BitInt or pointers
- so pun with an integer type if needed. */
- tree conv_elem_type = TREE_TYPE (perm_type);
- if (conv_code != ERROR_MARK
- && orig_elem_type[0]
- && TYPE_SIGN (orig_elem_type[0]) != TYPE_SIGN (conv_elem_type))
- conv_elem_type = signed_or_unsigned_type_for (TYPE_UNSIGNED
- (orig_elem_type[0]),
- conv_elem_type);
- conv_src_type = build_vector_type (conv_elem_type, nelts);
if (conv_code != ERROR_MARK
&& !supportable_convert_operation (conv_code, type, conv_src_type,
&conv_code))
@@ -4280,8 +4290,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
/* Otherwise, we can still have an intermediate sign change.
??? In that case we have two subsequent conversions.
We should be able to merge them. */
- else if (conv_code != ERROR_MARK
- && tree_nop_conversion_p (conv_src_type, perm_type))
+ else if (sign_change_p)
res = gimple_build (&stmts, VIEW_CONVERT_EXPR, conv_src_type, res);
/* Finally, apply the conversion. */
if (conv_code != ERROR_MARK)
--
2.52.0