https://gcc.gnu.org/g:badd64289a496c0fdb50f39fc2edeb4d124a8d0d
commit r16-6976-gbadd64289a496c0fdb50f39fc2edeb4d124a8d0d Author: Robin Dapp <[email protected]> Date: Wed Jan 21 08:20:48 2026 +0100 forwprop: More nop-conversion handling [PR123731]. 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. 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. Diff: --- gcc/testsuite/gcc.dg/vect/pr123731.c | 28 ++++++++++++++++++++++++++++ gcc/tree-ssa-forwprop.cc | 19 ++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/gcc/testsuite/gcc.dg/vect/pr123731.c b/gcc/testsuite/gcc.dg/vect/pr123731.c new file mode 100644 index 000000000000..81fdb5d53bc5 --- /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 bdc63a7a71bc..51de6308a091 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)))
