On Wed, Jan 21, 2026 at 10:18 PM Robin Dapp <[email protected]> wrote:
>
> Hi,
>
> Since relaxing the constraints for permutes in r16-6671 for simplifying
> vector constructors there is an additional case to be handled as it
> interacts with r16-5561 (that allows nop conversions).
>
> In
> vector(8) short unsigned int _4;
> short int _5;
> vector(4) unsigned int _17;
>
> _3 = *a_14(D);
> _2 = {_3, { 0, 0, 0, 0 }};
> _4 = VEC_PERM_EXPR <{ 0, 0, 0, 0, 0, 0, 0, 0 }, _2, { 0, 9, 11, 3, 10, 2,
> 9, 8 }>;
> _5 = BIT_FIELD_REF <_4, 16, 32>;
> d_16 = (unsigned int) _5;
> _17 = {d_16, d_16, d_16, d_16};
>
> we failed to consider that _5 is a signed type and directly converted to
> unsigned.
>
> With this patch we do
> _3 = *a_14(D);
> _5 = BIT_FIELD_REF <_3, 16, 48>;
> d_16 = (unsigned int) _5;
> _15 = VEC_PERM_EXPR <_3, _3, { 3, 3, 3, 3 }>;
> _1 = VIEW_CONVERT_EXPR<vector(4) short int>(_15);
> _21 = (vector(4) unsigned int) _1;
>
> where the two conversions can often be done in one instruction.
>
> Bootstrapped and regtested on x86 and power10, aarch64 still running.
> Regtested on riscv64.
OK.
Richard.
> Regards
> Robin
>
> PR tree-optimization/123731
>
> gcc/ChangeLog:
>
> * tree-ssa-forwprop.cc (simplify_vector_constructor): Handle nop
> conversion between during extraction.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/vect/pr123731.c: New test.
> ---
> gcc/testsuite/gcc.dg/vect/pr123731.c | 28 ++++++++++++++++++++++++++++
> gcc/tree-ssa-forwprop.cc | 19 ++++++++++++++++---
> 2 files changed, 44 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/vect/pr123731.c
>
> diff --git a/gcc/testsuite/gcc.dg/vect/pr123731.c
> b/gcc/testsuite/gcc.dg/vect/pr123731.c
> new file mode 100644
> index 00000000000..81fdb5d53bc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/pr123731.c
> @@ -0,0 +1,28 @@
> +/* { dg-do run } */
> +
> +typedef unsigned short A __attribute__ ((vector_size (4 * sizeof (short))));
> +typedef short B __attribute__ ((vector_size (8 * sizeof (short))));
> +typedef unsigned C __attribute__ ((vector_size (4 * sizeof (int))));
> +unsigned long long c;
> +
> +__attribute__ ((noipa)) void
> +foo (A *a)
> +{
> + C b[9] = {};
> + unsigned d = __builtin_convertvector (
> + __builtin_shufflevector ((A) {}, *a, 0, 5, 7, 3, 6, 2, 5, 4), B)[2];
> + b[0] += (C) {d, d, d, d};
> + c += b[0][0];
> +}
> +
> +int
> +main ()
> +{
> + A t = (A) {0, 0, 0, -6};
> + foo (&t);
> + if (sizeof (short) == 2
> + && sizeof (int) == 4
> + && __CHAR_BIT__ == 8
> + && c != -6U)
> + __builtin_abort ();
> +}
> diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
> index bdc63a7a71b..51de6308a09 100644
> --- a/gcc/tree-ssa-forwprop.cc
> +++ b/gcc/tree-ssa-forwprop.cc
> @@ -4137,9 +4137,15 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
> return false;
> tree mask_type, perm_type, conv_src_type;
> perm_type = TREE_TYPE (orig[0]);
> - conv_src_type = (nelts == refnelts
> - ? perm_type
> - : build_vector_type (TREE_TYPE (perm_type), nelts));
> + /* 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. */
> + tree conv_elem_type = TREE_TYPE (perm_type);
> + if (conv_code != ERROR_MARK
> + && orig_elem_type[0]
> + && tree_nop_conversion_p (orig_elem_type[0], conv_elem_type))
> + conv_elem_type = orig_elem_type[0];
> + 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))
> @@ -4257,6 +4263,8 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
> = converted_orig1 ? build_zero_cst (perm_type) : orig[1];
> tree res = gimple_build (&stmts, VEC_PERM_EXPR, perm_type,
> orig[0], orig1_for_perm, op2);
> + /* If we're building a smaller vector, extract the element
> + with the proper type. */
> if (nelts != refnelts)
> res = gimple_build (&stmts, BIT_FIELD_REF,
> conv_code != ERROR_MARK ? conv_src_type : type,
> @@ -4264,6 +4272,11 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
> TYPE_SIZE (conv_code != ERROR_MARK ? conv_src_type
> : type),
> bitsize_zero_node);
> + /* Otherwise, we can still have an intermediate sign change. */
> + else if (conv_code != ERROR_MARK
> + && tree_nop_conversion_p (conv_src_type, perm_type))
> + res = gimple_build (&stmts, VIEW_CONVERT_EXPR, conv_src_type, res);
> + /* Finally, apply the conversion. */
> if (conv_code != ERROR_MARK)
> res = gimple_build (&stmts, conv_code, type, res);
> else if (!useless_type_conversion_p (type, TREE_TYPE (res)))
> --
> 2.52.0