shuffle_slide_patterns did not verify that the endpoints of a combined
slideup+slidedown sequence actually correspond to OP0's and OP1's
expected positions, allowing a non-monotonic shuffle mask to be
accepted as a valid slide pattern. This produced wrong code at -O0
for masks such as { 7, 0, 7, 0 } on a 4-element vector, as reported
in PR target/126411.
This patch checks that d->perm[0] and d->perm[vlen - 1] correspond
to the expected OP0/OP1 boundary positions (vlen - slideup_cnt and
2 * vlen - 1 - slideup_cnt respectively), and rejects the pattern
otherwise. need_slideup_p is also added to the existing second-pivot
rejection check.
gcc/ChangeLog:
PR target/126411
* config/riscv/riscv-v.cc (shuffle_slide_patterns): Check that
the sequence endpoints correspond to OP0's and OP1's expected
positions and also reject a second pivot when need_slideup_p is set.
gcc/testsuite/ChangeLog:
PR target/126411
* gcc.target/riscv/rvv/base/bug126411.c: New test.
Suggested-by: Raphael M Zinsly <[email protected]>
Signed-off-by: Souradipto Das <[email protected]>
---
Bootstrapped and regtested on riscv64-unknown-linux-gnu via qemu-user
(rv64gcv, lp64d): full gcc.target/riscv/rvv/*.exp run before and
after this patch shows identical failure/xfail/unresolved/unsupported
counts, with the only difference being the new test passing (114093
-> 114095 expected passes). Verified by hand that the original
reproducer flips from wrong-code (checksum 0x0) to correct output
(checksum 0x46) with this patch applied.
gcc/config/riscv/riscv-v.cc | 7 ++++++-
.../gcc.target/riscv/rvv/base/bug126411.c | 15 +++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/bug126411.c
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index d8d20925dd5..a465c052d79 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -3829,6 +3829,11 @@ shuffle_slide_patterns (struct expand_vec_perm_d *d)
}
else
return false;
+
+ /* Check if the beginning and end of the sequence corresponds to OP0 and
OP1 respectively */
+ if (!(known_eq (d->perm[0], vlen - slideup_cnt) && known_eq
(d->perm[vlen - 1], 2 * vlen - 1 - slideup_cnt)))
+ return false;
+
}
/* Check for a monotonic sequence with one or two pivots. */
@@ -3842,7 +3847,7 @@ shuffle_slide_patterns (struct expand_vec_perm_d *d)
&& maybe_ne (d->perm[i], d->perm[i - 1] + 1))
{
/* A second pivot would indicate the vector length and is in OP0. */
- if (known_ge (d->perm[i], vec_len) || pivot == -1 || len != 0)
+ if (known_ge (d->perm[i], vec_len) || pivot == -1 || len != 0 ||
need_slideup_p)
return false;
len = i;
}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/bug126411.c
b/gcc/testsuite/gcc.target/riscv/rvv/base/bug126411.c
new file mode 100644
index 00000000000..738d9247cab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/bug126411.c
@@ -0,0 +1,15 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-options "-march=rv64gcv -O0" } */
+
+#include <stdint.h>
+
+typedef int8_t v4i8 __attribute__((vector_size(4)));
+v4i8 g2 = { 7, 0, 8, 70 }, g12;
+
+int main()
+{
+ g12 = __builtin_shufflevector(g2, g2, 7, 0, 7, 0);
+ if (g12[2] != 70)
+ __builtin_abort();
+ return 0;
+}
--
2.43.0