aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2025-07-09 16:39:20 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2025-07-09 16:39:20 +0100
commit41c446389446a357172883389e36fd10c882ce6d (patch)
treec096cbbf8959e9379ab1af41e6a8ac3661cfd117 /gcc/testsuite
parent76db38d811a63a603deedfe327d5e201fc820444 (diff)
downloadgcc-41c446389446a357172883389e36fd10c882ce6d.zip
gcc-41c446389446a357172883389e36fd10c882ce6d.tar.gz
gcc-41c446389446a357172883389e36fd10c882ce6d.tar.bz2
aarch64: Some fixes for SVE INDEX constants
When using SVE INDEX to load an Advanced SIMD vector, we need to take account of the different element ordering for big-endian targets. For example, when big-endian targets store the V4SI constant { 0, 1, 2, 3 } in registers, 0 becomes the most significant element, whereas INDEX always operates from the least significant element. A big-endian target would therefore load V4SI { 0, 1, 2, 3 } using: INDEX Z0.S, #3, #-1 rather than little-endian's: INDEX Z0.S, #0, #1 While there, I noticed that we would only check the first vector in a multi-vector SVE constant, which would trigger an ICE if the other vectors turned out to be invalid. This is pretty difficult to trigger at the moment, since we only allow single-register modes to be used as frontend & middle-end vector modes, but it can be seen using the RTL frontend. gcc/ * config/aarch64/aarch64.cc (aarch64_sve_index_series_p): New function, split out from... (aarch64_simd_valid_imm): ...here. Account for the different SVE and Advanced SIMD element orders on big-endian targets. Check each vector in a structure mode. gcc/testsuite/ * gcc.dg/rtl/aarch64/vec-series-1.c: New test. * gcc.dg/rtl/aarch64/vec-series-2.c: Likewise. * gcc.target/aarch64/sve/acle/general/dupq_2.c: Fix expected output for this big-endian test. * gcc.target/aarch64/sve/acle/general/dupq_4.c: Likewise. * gcc.target/aarch64/sve/vec_init_3.c: Restrict to little-endian targets and add more tests. * gcc.target/aarch64/sve/vec_init_4.c: New big-endian version of vec_init_3.c.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c35
-rw-r--r--gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c35
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c114
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c209
6 files changed, 393 insertions, 4 deletions
diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c
new file mode 100644
index 0000000..6f795c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-1.c
@@ -0,0 +1,35 @@
+/* { dg-do compile { target aarch64*-*-* } } */
+/* { dg-options "-O2 -msve-vector-bits=256 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+#pragma GCC target "+sve"
+
+svint64x2_t __RTL (startwith ("vregs")) foo ()
+{
+ (function "foo"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 3 (set (reg:VNx4DI <0>)
+ (const_vector:VNx4DI [(const_int 11)
+ (const_int 12)
+ (const_int 13)
+ (const_int 14)
+ (const_int 15)
+ (const_int 16)
+ (const_int 17)
+ (const_int 18)])))
+ (insn 4 (set (reg:VNx4DI v0) (reg:VNx4DI <0>)))
+ (insn 5 (use (reg:VNx4DI v0)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+ (crtl (return_rtx (reg:VNx4DI v0)))
+ ) ;; function
+}
+
+/* { dg-final { scan-assembler {\tindex\tz0\.d, #11, #1\n} } } */
+/* { dg-final { scan-assembler {\tindex\tz1\.d, #15, #1\n} } } */
diff --git a/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c
new file mode 100644
index 0000000..17e46cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/rtl/aarch64/vec-series-2.c
@@ -0,0 +1,35 @@
+/* { dg-do compile { target aarch64*-*-* } } */
+/* { dg-options "-O2 -msve-vector-bits=256 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+#pragma GCC target "+sve"
+
+svint64x2_t __RTL (startwith ("vregs")) foo ()
+{
+ (function "foo"
+ (insn-chain
+ (block 2
+ (edge-from entry (flags "FALLTHRU"))
+ (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+ (cnote 2 NOTE_INSN_FUNCTION_BEG)
+ (insn 3 (set (reg:VNx4DI <0>)
+ (const_vector:VNx4DI [(const_int -16)
+ (const_int -15)
+ (const_int -14)
+ (const_int -13)
+ (const_int -12)
+ (const_int -11)
+ (const_int -10)
+ (const_int -9)])))
+ (insn 4 (set (reg:VNx4DI v0) (reg:VNx4DI <0>)))
+ (insn 5 (use (reg:VNx4DI v0)))
+ (edge-to exit (flags "FALLTHRU"))
+ ) ;; block 2
+ ) ;; insn-chain
+ (crtl (return_rtx (reg:VNx4DI v0)))
+ ) ;; function
+}
+
+/* { dg-final { scan-assembler {\tindex\tz0\.d, #-16, #1\n} } } */
+/* { dg-final { scan-assembler {\tindex\tz1\.d, #-12, #1\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c
index 218a660..13ebb9f 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c
@@ -10,6 +10,6 @@ dupq (int x)
return svdupq_s32 (x, 1, 2, 3);
}
-/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #3, #-1} } } */
+/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #0, #1\n} } } */
/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */
/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c
index cbee6f2..13d27e2 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c
@@ -10,6 +10,6 @@ dupq (int x)
return svdupq_s32 (0, 1, x, 3);
}
-/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #3, #-1} } } */
+/* { dg-final { scan-assembler {\tindex\tz[0-9]+\.s, #0, #1\n} } } */
/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */
/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c
index 25910db..5100a87 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -mlittle-endian" } */
/* { dg-final { check-function-bodies "**" "" "" } } */
typedef char v16qi __attribute__ ((vector_size (16)));
@@ -8,7 +8,7 @@ typedef short v8hi __attribute__ ((vector_size (16)));
typedef short v4hi __attribute__ ((vector_size (8)));
typedef int v4si __attribute__ ((vector_size (16)));
typedef int v2si __attribute__ ((vector_size (8)));
-typedef long v2di __attribute__ ((vector_size (16)));
+typedef long long v2di __attribute__ ((vector_size (16)));
/*
** f_v16qi:
@@ -97,3 +97,113 @@ g_v4si (void)
{
return (v4si){ 3, -1, -5, -9 };
}
+
+/*
+** g_min_1:
+** index z0\.s, #-16, #1
+** ret
+*/
+v4si
+g_min_1 (void)
+{
+ return (v4si){ -16, -15, -14, -13 };
+}
+
+/*
+** g_min_min:
+** index z0\.s, #-16, #-16
+** ret
+*/
+v4si
+g_min_min (void)
+{
+ return (v4si){ -16, -32, -48, -64 };
+}
+
+/*
+** g_min_max:
+** index z0\.s, #-16, #15
+** ret
+*/
+v4si
+g_min_max (void)
+{
+ return (v4si){ -16, -1, 14, 29 };
+}
+
+/*
+** g_max_1:
+** index z0\.s, #15, #1
+** ret
+*/
+v4si
+g_max_1 (void)
+{
+ return (v4si){ 15, 16, 17, 18 };
+}
+
+/*
+** g_max_min:
+** index z0\.s, #15, #-16
+** ret
+*/
+v4si
+g_max_min (void)
+{
+ return (v4si){ 15, -1, -17, -33 };
+}
+
+/*
+** g_max_max:
+** index z0\.s, #15, #15
+** ret
+*/
+v4si
+g_max_max (void)
+{
+ return (v4si){ 15, 30, 45, 60 };
+}
+
+/*
+** g_ob_1:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_1 (void)
+{
+ return (v4si){ -17, -16, -15, -14 };
+}
+
+/*
+** g_ob_2:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_2 (void)
+{
+ return (v4si){ 16, 17, 18, 19 };
+}
+
+/*
+** g_ob_3:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_3 (void)
+{
+ return (v4si){ 0, -17, -34, -51 };
+}
+
+/*
+** g_ob_4:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_4 (void)
+{
+ return (v4si){ 0, 16, 32, 48 };
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c
new file mode 100644
index 0000000..0681d95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_init_4.c
@@ -0,0 +1,209 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+typedef char v8qi __attribute__ ((vector_size (8)));
+typedef short v8hi __attribute__ ((vector_size (16)));
+typedef short v4hi __attribute__ ((vector_size (8)));
+typedef int v4si __attribute__ ((vector_size (16)));
+typedef int v2si __attribute__ ((vector_size (8)));
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+/*
+** f_v16qi:
+** index z0\.b, #15, #-1
+** ret
+*/
+v16qi
+f_v16qi (void)
+{
+ return (v16qi){ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+}
+
+/*
+** f_v8qi:
+** index z0\.b, #7, #-1
+** ret
+*/
+v8qi
+f_v8qi (void)
+{
+ return (v8qi){ 0, 1, 2, 3, 4, 5, 6, 7 };
+}
+
+/*
+** f_v8hi:
+** index z0\.h, #7, #-1
+** ret
+*/
+v8hi
+f_v8hi (void)
+{
+ return (v8hi){ 0, 1, 2, 3, 4, 5, 6, 7 };
+}
+
+/*
+** f_v4hi:
+** index z0\.h, #3, #-1
+** ret
+*/
+v4hi
+f_v4hi (void)
+{
+ return (v4hi){ 0, 1, 2, 3 };
+}
+
+/*
+** f_v4si:
+** index z0\.s, #3, #-1
+** ret
+*/
+v4si
+f_v4si (void)
+{
+ return (v4si){ 0, 1, 2, 3 };
+}
+
+/*
+** f_v2si:
+** index z0\.s, #1, #-1
+** ret
+*/
+v2si
+f_v2si (void)
+{
+ return (v2si){ 0, 1 };
+}
+
+/*
+** f_v2di:
+** index z0\.d, #1, #-1
+** ret
+*/
+v2di
+f_v2di (void)
+{
+ return (v2di){ 0, 1 };
+}
+
+/*
+** g_v4si:
+** index z0\.s, #-9, #4
+** ret
+*/
+v4si
+g_v4si (void)
+{
+ return (v4si){ 3, -1, -5, -9 };
+}
+
+/*
+** g_min_1:
+** index z0\.s, #-16, #1
+** ret
+*/
+v4si
+g_min_1 (void)
+{
+ return (v4si){ -13, -14, -15, -16 };
+}
+
+/*
+** g_min_min:
+** index z0\.s, #-16, #-16
+** ret
+*/
+v4si
+g_min_min (void)
+{
+ return (v4si){ -64, -48, -32, -16 };
+}
+
+/*
+** g_min_max:
+** index z0\.s, #-16, #15
+** ret
+*/
+v4si
+g_min_max (void)
+{
+ return (v4si){ 29, 14, -1, -16 };
+}
+
+/*
+** g_max_1:
+** index z0\.s, #15, #1
+** ret
+*/
+v4si
+g_max_1 (void)
+{
+ return (v4si){ 18, 17, 16, 15 };
+}
+
+/*
+** g_max_min:
+** index z0\.s, #15, #-16
+** ret
+*/
+v4si
+g_max_min (void)
+{
+ return (v4si){ -33, -17, -1, 15 };
+}
+
+/*
+** g_max_max:
+** index z0\.s, #15, #15
+** ret
+*/
+v4si
+g_max_max (void)
+{
+ return (v4si){ 60, 45, 30, 15 };
+}
+
+/*
+** g_ob_1:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_1 (void)
+{
+ return (v4si){ -14, -15, -16, -17 };
+}
+
+/*
+** g_ob_2:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_2 (void)
+{
+ return (v4si){ 19, 18, 17, 16 };
+}
+
+/*
+** g_ob_3:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_3 (void)
+{
+ return (v4si){ -51, -34, -17, 0 };
+}
+
+/*
+** g_ob_4:
+** ((?!index).)*
+** ret
+*/
+v4si
+g_ob_4 (void)
+{
+ return (v4si){ 48, 32, 16, 0 };
+}