[gcc r17-3401] aarch64: Swap the zeroness flags when swapping vec_perm operands [PR126597]
Kyrylo Tkachov via Gcc-cvs <[email protected]>
| Newsgroups | gmane.comp.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://gcc.gnu.org/g:75b259d068e1db2c8ac2246e3118dd5d24724674 commit r17-3401-g75b259d068e1db2c8ac2246e3118dd5d24724674 Author: Kyrylo Tkachov <[email protected]> Date: Tue Aug 18 14:19:57 2026 +0200 aarch64: Swap the zeroness flags when swapping vec_perm operands [PR126597] aarch64_expand_vec_perm_const_1 normalizes a permutation whose first index selects the second operand by rotating the indices and swapping op0 and op1. It left zero_op0_p and zero_op1_p pointing at the old operands, so the later recognizers that consult them, aarch64_evpc_and and aarch64_evpc_tbl, read the wrong vector. Swap the two flags together with the operands. For typedef int v4si __attribute__ ((vector_size (16))); v4si f (v4si x) { const v4si m = { 4, 1, 2, 3 }; return __builtin_shuffle (x, (v4si) { 0, 0, 0, 0 }, m); } at -O0 the AND was applied to the all-zero operand, so the function returned {0,0,0,0} instead of {0,x1,x2,x3}: sub sp, sp, #32 str q0, [sp] adrp x0, .LC0 add x0, x0, :lo12:.LC0 ldr q31, [x0] str q31, [sp, 16] movi v31.4s, 0 fmov s31, s31 mov v0.16b, v31.16b add sp, sp, 32 ret With the fix the AND is applied to the incoming vector: sub sp, sp, #32 str q0, [sp] adrp x0, .LC0 add x0, x0, :lo12:.LC0 ldr q31, [x0] str q31, [sp, 16] ldr q30, [sp] adrp x0, .LC1 add x0, x0, :lo12:.LC1 ldr q31, [x0] and v31.16b, v30.16b, v31.16b mov v0.16b, v31.16b add sp, sp, 32 ret Bootstrapped and tested on aarch64-none-linux-gnu. gcc/ChangeLog: PR target/126597 * config/aarch64/aarch64.cc (aarch64_expand_vec_perm_const_1): Swap zero_op0_p and zero_op1_p along with the operands. gcc/testsuite/ChangeLog: PR target/126597 * gcc.target/aarch64/pr126597.c: New test. Signed-off-by: Kyrylo Tkachov <[email protected]> Diff: --- gcc/config/aarch64/aarch64.cc | 1 + gcc/testsuite/gcc.target/aarch64/pr126597.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index fdffb13ad222..8a788a5c7e41 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -28772,6 +28772,7 @@ aarch64_expand_vec_perm_const_1 (struct expand_vec_perm_d *d) { d->perm.rotate_inputs (1); std::swap (d->op0, d->op1); + std::swap (d->zero_op0_p, d->zero_op1_p); } if (((d->vec_flags == VEC_ADVSIMD && TARGET_SIMD) diff --git a/gcc/testsuite/gcc.target/aarch64/pr126597.c b/gcc/testsuite/gcc.target/aarch64/pr126597.c new file mode 100644 index 000000000000..922d673fa6a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr126597.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-O0" } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +__attribute__((noipa)) v4si +f (v4si x) +{ + const v4si mask = { 4, 1, 2, 3 }; + return __builtin_shuffle (x, (v4si) { 0, 0, 0, 0 }, mask); +} + +int +main (void) +{ + v4si x = { 1, 2, 3, 4 }; + v4si r = f (x); + if (r[0] != 0 || r[1] != 2 || r[2] != 3 || r[3] != 4) + __builtin_abort (); + return 0; +}