https://gcc.gnu.org/g:e8fd095091ebfc0c4adc1c7f6607ab30b25b3a05
commit r16-6292-ge8fd095091ebfc0c4adc1c7f6607ab30b25b3a05 Author: Robin Dapp <[email protected]> Date: Mon Dec 15 13:01:40 2025 +0100 forwprop: Check type conversion in pack/unpack [PR123117]. When using pack or unpack in the simplification of a vector constructor we must make sure that the original BIT_FIELD_REF was no sign-changing nop conversion. If it was we cannot safely pack/unpack as that would skip sign or zero extensions. This patch adds useless_type_conversion_p to both paths. PR tree-optimization/123117 gcc/ChangeLog: * tree-ssa-forwprop.cc (simplify_vector_constructor): Check if we had a nop conversion and don't use pack/unpack in that case. gcc/testsuite/ChangeLog: * gcc.target/loongarch/vector/lsx/pr123117.c: New test. Diff: --- gcc/testsuite/gcc.target/loongarch/vector/lsx/pr123117.c | 16 ++++++++++++++++ gcc/tree-ssa-forwprop.cc | 12 ++++++++++++ 2 files changed, 28 insertions(+) diff --git a/gcc/testsuite/gcc.target/loongarch/vector/lsx/pr123117.c b/gcc/testsuite/gcc.target/loongarch/vector/lsx/pr123117.c new file mode 100644 index 000000000000..c9683e9629b8 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/vector/lsx/pr123117.c @@ -0,0 +1,16 @@ +/* { dg-options "-mlsx -O1" } */ + +#define BS_VEC(type, num) type __attribute__((vector_size(num * sizeof(type)))) +#define T BS_VEC(unsigned, 4) + +int main () +{ + BS_VEC(long int, 2) BS_VAR_0[1]; + BS_VEC(int, 4) tt = (BS_VEC(int, 4)){0x9e47d3d2, 0, 0, 0}; + asm("":"+f"(tt)); + BS_VEC(unsigned int, 2) SHUF = __builtin_shufflevector((T)tt, (T)tt, 0, 1); + BS_VAR_0[0] = __builtin_convertvector(SHUF, BS_VEC(long int, 2)); + + if (BS_VAR_0[0][0] != 0x000000009e47d3d2) + __builtin_abort (); +} diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc index 2200fc04918d..17bfa2a99dc4 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -3848,6 +3848,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) orig[0] = NULL; orig[1] = NULL; + tree orig_elem_type[2] = {}; conv_code = ERROR_MARK; bool maybe_ident = true; bool maybe_blend[2] = { true, true }; @@ -3902,6 +3903,11 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (j < 2) { orig[j] = ref; + /* Track what element type was actually extracted (which may + differ in signedness from the vector's element type due to + tree_nop_conversion_p). */ + if (!orig_elem_type[j]) + orig_elem_type[j] = TREE_TYPE (op1); if (elem != i || j != 0) maybe_ident = false; if (elem != i) @@ -4011,6 +4017,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) if (CONVERT_EXPR_CODE_P (conv_code) && (2 * TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig[0]))) == TYPE_PRECISION (TREE_TYPE (type))) + && orig_elem_type[0] + && useless_type_conversion_p (orig_elem_type[0], + TREE_TYPE (type)) && mode_for_vector (as_a <scalar_mode> (TYPE_MODE (TREE_TYPE (TREE_TYPE (orig[0])))), nelts * 2).exists () @@ -4050,6 +4059,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) else if (CONVERT_EXPR_CODE_P (conv_code) && (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig[0]))) == 2 * TYPE_PRECISION (TREE_TYPE (type))) + && orig_elem_type[0] + && useless_type_conversion_p (orig_elem_type[0], + TREE_TYPE (type)) && mode_for_vector (as_a <scalar_mode> (TYPE_MODE (TREE_TYPE (TREE_TYPE (orig[0])))),
