https://gcc.gnu.org/g:ca6ddc9ecd74b89284ecede2ed90f768f70d88a5
commit r17-5328-gca6ddc9ecd74b89284ecede2ed90f768f70d88a5 Author: Igor Shevlyakov <[email protected]> Date: Sun Oct 18 14:58:39 2026 -0700 match.pd: Index BIT_FIELD_REF of VEC_PERM_EXPR inputs by their length The BIT_FIELD_REF <VEC_PERM_EXPR <a, b, sel>> fold takes its element count from the selector, i.e. from the result. It then uses that count to reduce selector values, to choose between a and b, and to rebase indices into b. A constant VEC_PERM_EXPR may have inputs with a different number of elements than its result. When a and b are wider, an index into a at or above the result length is taken as an index into b: silent wrong code. When they are narrower, an index into b is taken as an index past the end of a, which fails GIMPLE verification. Besides explicit element extraction, vector lowering produces such BIT_FIELD_REFs when it lowers an unsupported narrowing permute whose input is a narrowing permute the target supports, and forwprop then folds them. Use the element count of the inputs. gcc/ChangeLog: * match.pd (BIT_FIELD_REF (vec_perm ...)): Take the element count from the inputs, not the selector. gcc/testsuite/ChangeLog: * gcc.dg/torture/vec-perm-bitfield-ref-narrow-input-1.c: New test. * gcc.dg/torture/vec-perm-bitfield-ref-wide-input-1.c: New test. Signed-off-by: Igor Shevlyakov <[email protected]> Diff: --- gcc/match.pd | 5 +- .../torture/vec-perm-bitfield-ref-narrow-input-1.c | 53 ++++++++++++++++++++++ .../torture/vec-perm-bitfield-ref-wide-input-1.c | 53 ++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) diff --git a/gcc/match.pd b/gcc/match.pd index 629114591a2b..7bb9126065dc 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -11042,8 +11042,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) unsigned HOST_WIDE_INT nelts, idx; unsigned HOST_WIDE_INT nelts_op = 0; } + /* NELTS is the number of elements in each input, which may differ + from that of the result; the selector indexes their concatenation. */ (if (constant_multiple_p (tree_to_poly_uint64 (@rpos), elem_size, &idx) - && VECTOR_CST_NELTS (@3).is_constant (&nelts) + && VECTOR_CST_NELTS (@3).is_constant () + && TYPE_VECTOR_SUBPARTS (TREE_TYPE (@1)).is_constant (&nelts) && (known_eq (size, elem_size) || (constant_multiple_p (size, elem_size, &nelts_op) && pow2p_hwi (nelts_op)))) diff --git a/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-narrow-input-1.c b/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-narrow-input-1.c new file mode 100644 index 000000000000..43d4831b702c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-narrow-input-1.c @@ -0,0 +1,53 @@ +/* BIT_FIELD_REF of a VEC_PERM_EXPR with inputs narrower than the result. */ +/* { dg-do run } */ +/* { dg-additional-options "-fgimple -Wno-psabi" } */ + +typedef short v8hi __attribute__((vector_size(16))); +typedef short v4hi __attribute__((vector_size(8))); +typedef short v2hi __attribute__((vector_size(4))); + +v4hi a, b; +short s; +v2hi r; + +/* One element. */ +void __attribute__((noipa)) __GIMPLE() f1 () +{ + v4hi a_; v4hi b_; v8hi c_; short e_; + a_ = a; b_ = b; + c_ = __VEC_PERM (a_, b_, _Literal (v8hi) { 0, 5, 2, 3, 4, 5, 6, 7 }); + e_ = __BIT_FIELD_REF <short> (c_, 16, 16); + s = e_; +} + +/* A subvector. */ +void __attribute__((noipa)) __GIMPLE() f2 () +{ + v4hi a_; v4hi b_; v8hi c_; v2hi e_; + a_ = a; b_ = b; + c_ = __VEC_PERM (a_, b_, _Literal (v8hi) { 0, 1, 6, 7, 4, 5, 2, 3 }); + e_ = __BIT_FIELD_REF <v2hi> (c_, 32, 32); + r = e_; +} + +int +main () +{ + for (int i = 0; i < 4; i++) + { + a[i] = i + 1; + b[i] = i + 101; + } + + f1 (); + /* c[1] = b1. */ + if (s != 102) + __builtin_abort (); + + f2 (); + /* c[2] = b2, c[3] = b3. */ + if (r[0] != 103 || r[1] != 104) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-wide-input-1.c b/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-wide-input-1.c new file mode 100644 index 000000000000..deb7247ed654 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/vec-perm-bitfield-ref-wide-input-1.c @@ -0,0 +1,53 @@ +/* BIT_FIELD_REF of a VEC_PERM_EXPR with inputs wider than the result. */ +/* { dg-do run } */ +/* { dg-additional-options "-fgimple -Wno-psabi" } */ + +typedef short v8hi __attribute__((vector_size(16))); +typedef short v4hi __attribute__((vector_size(8))); +typedef short v2hi __attribute__((vector_size(4))); + +v8hi a, b; +short s; +v2hi r; + +/* One element. */ +void __attribute__((noipa)) __GIMPLE() f1 () +{ + v8hi a_; v8hi b_; v4hi c_; short e_; + a_ = a; b_ = b; + c_ = __VEC_PERM (a_, b_, _Literal (v4hi) { 13, 6, 2, 9 }); + e_ = __BIT_FIELD_REF <short> (c_, 16, 16); + s = e_; +} + +/* A subvector. */ +void __attribute__((noipa)) __GIMPLE() f2 () +{ + v8hi a_; v8hi b_; v4hi c_; v2hi e_; + a_ = a; b_ = b; + c_ = __VEC_PERM (a_, b_, _Literal (v4hi) { 13, 2, 6, 7 }); + e_ = __BIT_FIELD_REF <v2hi> (c_, 32, 32); + r = e_; +} + +int +main () +{ + for (int i = 0; i < 8; i++) + { + a[i] = i + 1; + b[i] = i + 101; + } + + f1 (); + /* c[1] = a6. */ + if (s != 7) + __builtin_abort (); + + f2 (); + /* c[2] = a6, c[3] = a7. */ + if (r[0] != 7 || r[1] != 8) + __builtin_abort (); + + return 0; +}
