Port the v{ld,st}{2,3,4} families of intrinsics to the pragma-based
framework, and add corresponding assembly tests for each variant.
Lowering the functions to `IFN_LOAD_LANES`/`IFN_STORE_LANES` required
adding extending the expanders for `vec_load_lanes<mode><vstruct_elt>`
and `vec_store_lanes<mode><vstruct_elt>` to cover tuples of D-sized
vectors. This made the loop in `vect-early-break_39.c` fail to
vectorize.
gcc/ChangeLog:
* config/aarch64/aarch64-builtins.cc (TYPES_STORE1,
TYPES_STORESTRUCT, TYPES_STORE1_U, TYPES_STORESTRUCT_U,
TYPES_STORE1_P, TYPES_STORESTRUCT_P): Delete macros.
(aarch64_expand_pragma_builtin): Delete cases handling
`UNSPEC_LD{2,3,4}` and `UNSPEC_ST{2,3,4}`.
* config/aarch64/aarch64-neon-builtins-base.cc
(build_tuple_get_array): New function.
(build_tuple_get): Call `build_tuple_get_array`.
(struct gimple_load_store_interleaved): New struct.
* config/aarch64/aarch64-neon-builtins-base.def (vld2, vld2q,
vld3, vld3q, vld4, vld4q, vst2, vst2q, vst3, vst3q, vst4,
vst4q): Declare new intrinsics.
* config/aarch64/aarch64-simd-builtins.def: Delete builtin
function declarations.
* config/aarch64/aarch64-simd-pragma-builtins.def: Delete
intrinsic function declarations.
* config/aarch64/aarch64-simd.md
(vec_load_lanes<mode><vstruct_elt>,
@aarch64_ld<nregs><vstruct_elt>, aarch64_simd_ld2<vstruct_elt>,
aarch64_simd_ld3<vstruct_elt>, aarch64_simd_ld4<vstruct_elt>,
aarch64_ld2<vstruct_elt>_dreg, aarch64_ld3<vstruct_elt>_dreg,
aarch64_ld4<vstruct_elt>_dreg): Replace with...
(vec_load_lanes<mode><vstruct_elt>, @aarch64_load_interleaved<mode>):
...these.
(vec_store_lanes<mode><vstruct_elt>,
@aarch64_st<nregs><vstruct_elt>, aarch64_simd_st2<vstruct_elt>,
aarch64_simd_st3<vstruct_elt>, aarch64_simd_st4<vstruct_elt>,
aarch64_st2<vstruct_elt>_dreg, aarch64_st3<vstruct_elt>_dreg,
aarch64_st4<vstruct_elt>_dreg): Replace with...
(vec_store_lanes<mode><vstruct_elt>, @aarch64_store_interleaved<mode>):
...these.
* config/aarch64/aarch64.md
(UNSPEC_LD2, UNSPEC_LD2_DREG, UNSPEC_LD3, UNSPEC_LD3_DREG,
UNSPEC_LD4, UNSPEC_LD4_DREG): Replace with ...
(UNSPEC_LOAD_INTERLEAVED): ...this.
(UNSPEC_ST2, UNSPEC_ST2_DREG, UNSPEC_ST3, UNSPEC_ST3_DREG,
UNSPEC_ST4, UNSPEC_ST4_DREG): Replace with ...
(UNSPEC_STORE_INTERLEAVED): ...this.
* config/aarch64/iterators.md (VSTRUCT_DNX): New iterator.
gcc/testsuite/ChangeLog:
* gcc.dg/vect/vect-early-break_39.c: Mark as `xfail`.
* gcc.target/aarch64/pr99873_1.c: Update expected assembly (GCC
can now vectorize the loop tail as well as the loop body).
* gcc.target/aarch64/vld2-1.c: Update expected number of fwprop
iterations.
* gcc.target/aarch64/neon/vld2.c: New test.
* gcc.target/aarch64/neon/vld3.c: New test.
* gcc.target/aarch64/neon/vld4.c: New test.
* gcc.target/aarch64/neon/vst2.c: New test.
* gcc.target/aarch64/neon/vst3.c: New test.
* gcc.target/aarch64/neon/vst4.c: New test.
---
gcc/config/aarch64/aarch64-builtins.cc | 37 +-
.../aarch64/aarch64-neon-builtins-base.cc | 95 +++-
.../aarch64/aarch64-neon-builtins-base.def | 16 +
gcc/config/aarch64/aarch64-simd-builtins.def | 22 -
.../aarch64/aarch64-simd-pragma-builtins.def | 12 -
gcc/config/aarch64/aarch64-simd.md | 411 ++++--------------
gcc/config/aarch64/aarch64.md | 11 +-
gcc/config/aarch64/iterators.md | 4 +
.../gcc.dg/vect/vect-early-break_39.c | 7 +-
gcc/testsuite/gcc.target/aarch64/neon/vld2.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/neon/vld3.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/neon/vld4.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/neon/vst2.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/neon/vst3.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/neon/vst4.c | 228 ++++++++++
gcc/testsuite/gcc.target/aarch64/pr99873_1.c | 9 +-
gcc/testsuite/gcc.target/aarch64/vld2-1.c | 2 +-
17 files changed, 1564 insertions(+), 430 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vld2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vld3.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vld4.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vst2.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vst3.c
create mode 100644 gcc/testsuite/gcc.target/aarch64/neon/vst4.c
diff --git a/gcc/config/aarch64/aarch64-builtins.cc
b/gcc/config/aarch64/aarch64-builtins.cc
index 75d6cea7b13..cbb68d7b84f 100644
--- a/gcc/config/aarch64/aarch64-builtins.cc
+++ b/gcc/config/aarch64/aarch64-builtins.cc
@@ -377,27 +377,6 @@
aarch64_types_loadstruct_lane_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
qualifier_poly, qualifier_struct_load_store_lane_index };
#define TYPES_LOADSTRUCT_LANE_P (aarch64_types_loadstruct_lane_p_qualifiers)
-/* The first argument (return type) of a store should be void type,
- which we represent with qualifier_void. Their first operand will be
- a DImode pointer to the location to store to, so we must use
- qualifier_map_mode | qualifier_pointer to build a pointer to the
- element type of the vector. */
-static enum aarch64_type_qualifiers
-aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
- = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
-#define TYPES_STORE1 (aarch64_types_store1_qualifiers)
-#define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
-static enum aarch64_type_qualifiers
-aarch64_types_store1_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
- = { qualifier_void, qualifier_pointer_map_mode, qualifier_unsigned };
-#define TYPES_STORE1_U (aarch64_types_store1_u_qualifiers)
-#define TYPES_STORESTRUCT_U (aarch64_types_store1_u_qualifiers)
-static enum aarch64_type_qualifiers
-aarch64_types_store1_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
- = { qualifier_void, qualifier_pointer_map_mode, qualifier_poly };
-#define TYPES_STORE1_P (aarch64_types_store1_p_qualifiers)
-#define TYPES_STORESTRUCT_P (aarch64_types_store1_p_qualifiers)
-
static enum aarch64_type_qualifiers
aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
= { qualifier_void, qualifier_pointer_map_mode,
@@ -4241,12 +4220,6 @@ aarch64_expand_pragma_builtin (tree exp, rtx target,
gcc_unreachable ();
break;
- case UNSPEC_LD2:
- case UNSPEC_LD3:
- case UNSPEC_LD4:
- icode = code_for_aarch64_ld (ops[0].mode, ops[0].mode);
- break;
-
case UNSPEC_LD2_DUP:
aarch64_dereference_pointer (&ops[1], GET_MODE_INNER (ops[0].mode), 2);
icode = code_for_aarch64_simd_ld2r (ops[0].mode);
@@ -4293,12 +4266,6 @@ aarch64_expand_pragma_builtin (tree exp, rtx target,
icode = code_for_aarch64_get_lane (ops[1].mode);
break;
- case UNSPEC_ST2:
- case UNSPEC_ST3:
- case UNSPEC_ST4:
- icode = code_for_aarch64_st (ops[1].mode, ops[1].mode);
- break;
-
case UNSPEC_ST2_LANE:
case UNSPEC_ST3_LANE:
case UNSPEC_ST4_LANE:
@@ -4752,7 +4719,9 @@ aarch64_fold_to_val (gcall *stmt, gimple_stmt_iterator
*gsi,
tree
aarch64_dereference (tree addr, tree type)
{
- tree elt_type = (VECTOR_TYPE_P (type) ? TREE_TYPE (type) : type);
+ tree elt_type = VECTOR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE
+ ? TREE_TYPE (type)
+ : type;
tree elt_ptr_type = build_pointer_type_for_mode (elt_type, VOIDmode, true);
tree zero = build_zero_cst (elt_ptr_type);
/* Use element type alignment. */
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
index 19786d6de9a..a70530d3c78 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.cc
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.cc
@@ -144,21 +144,25 @@ build_shift_right (tree type, tree val, tree amount)
build_int_cst (TREE_TYPE (amount), bits - 1));
}
-/* Build a `TUPLE.val[INDEX]` expression. */
+/* Build `TUPLE.val`. */
tree
-build_tuple_get (tree tuple, tree index)
+build_tuple_get_array (tree tuple)
{
auto tuple_type = TREE_TYPE (tuple);
auto field = tuple_type_field (tuple_type);
auto array_type = TREE_TYPE (field);
- auto vec_type = TREE_TYPE (array_type);
-
- auto field_ref = fold_build3 (COMPONENT_REF, array_type, unshare_expr
(tuple),
- field, NULL_TREE);
- auto array_ref
- = build4 (ARRAY_REF, vec_type, field_ref, index, NULL_TREE, NULL_TREE);
+ return fold_build3 (COMPONENT_REF, array_type, unshare_expr (tuple), field,
+ NULL_TREE);
+}
- return array_ref;
+/* Build a `TUPLE.val[INDEX]` expression. */
+tree
+build_tuple_get (tree tuple, tree index)
+{
+ auto field_ref = build_tuple_get_array (tuple);
+ auto array_type = TREE_TYPE (field_ref);
+ auto vec_type = TREE_TYPE (array_type);
+ return build4 (ARRAY_REF, vec_type, field_ref, index, NULL_TREE, NULL_TREE);
}
/* Build a `TUPLE.val[INDEX][LANE]` expression. */
@@ -1603,6 +1607,75 @@ public:
}
};
+template <bool load_p>
+struct gimple_load_store_interleaved : public gimple_function_base
+{
+ unsigned int call_properties (const function_instance &) const override
+ {
+ return load_p ? CP_READ_MEMORY : CP_WRITE_MEMORY;
+ }
+
+ rtx expand (function_expander &e) const override
+ {
+ auto tuple_mode = load_p ? e.result_mode () : e.args[1]->mode;
+ insn_code icode;
+
+ auto &ptr_arg = e.args[0];
+ ptr_arg = gen_rtx_MEM (tuple_mode, e.convert_to_pmode (ptr_arg));
+
+ switch (tuple_mode)
+ {
+ case V2x1DImode: case V2x1DFmode:
+ case V3x1DImode: case V3x1DFmode:
+ case V4x1DImode: case V4x1DFmode:
+ icode = load_p ? code_for_aarch64_simd_load_multiple (tuple_mode)
+ : code_for_aarch64_simd_store_multiple (tuple_mode);
+ break;
+ default:
+ icode = load_p ? code_for_aarch64_load_interleaved (tuple_mode)
+ : code_for_aarch64_store_interleaved (tuple_mode);
+ break;
+ }
+
+ gcc_assert (icode != CODE_FOR_nothing);
+ return e.use_exact_insn (icode);
+ }
+
+ gimple *fold (gimple_folder &f) const override
+ {
+ auto ptr = gimple_call_arg (f.call, 0);
+ auto tuple_type = load_p ? TREE_TYPE (f.lhs) : TREE_TYPE (gimple_call_arg
(f.call, 1));
+ auto array_type = TREE_TYPE (tuple_type_field (tuple_type));
+ auto vec_type = TREE_TYPE (array_type);
+
+ if (BYTES_BIG_ENDIAN)
+ return nullptr;
+
+ if (one_element_vector_type_p (vec_type))
+ return nullptr;
+
+ auto deref = aarch64_dereference (ptr, array_type);
+ if (load_p)
+ {
+ /* lhs = VIEW_CONVERT (.LOAD_LANES (*ptr)) */
+ auto array = build_var (array_type);
+ auto call = gimple_build_call_internal (IFN_LOAD_LANES, 1, deref);
+ gimple_seq_add_stmt_without_update (&f.stmts,call);
+ gimple_call_set_lhs (call, array);
+ return gimple_build_assign (f.lhs, build_cast (tuple_type, array));
+ }
+ else
+ {
+ /* *ptr = .STORE_LANES (tuple.val) */
+ auto tuple = gimple_call_arg (f.call, 1);
+ auto array = build_tuple_get_array (tuple);
+ auto call = gimple_build_call_internal (IFN_STORE_LANES, 1, array);
+ gimple_call_set_lhs (call, deref);
+ return call;
+ }
+ }
+};
+
// Reinterpret
NEON_FUNCTION (vreinterpret, vreinterpretq, gimple_reinterpret,)
@@ -1824,6 +1897,10 @@ NEON_FUNCTION (vluti4q_lane, vluti4q_laneq,
gimple_luti<4>,)
NEON_FUNCTION (vld1, vld1q, vldrq, gimple_load_store_multiple<true>,)
NEON_FUNCTION (vst1, vst1q, vstrq, gimple_load_store_multiple<false>,)
+// Load/Store interleaved tuples
+NEON_FUNCTION (vld2, vld2q, vld3, vld3q, vld4, vld4q,
gimple_load_store_interleaved<true>,)
+NEON_FUNCTION (vst2, vst2q, vst3, vst3q, vst4, vst4q,
gimple_load_store_interleaved<false>,)
+
// AES
NEON_FUNCTION (vaeseq, gimple_exact_insn<CODE_FOR_aarch64_crypto_aesev16qi>,)
NEON_FUNCTION (vaesdq, gimple_exact_insn<CODE_FOR_aarch64_crypto_aesdv16qi>,)
diff --git a/gcc/config/aarch64/aarch64-neon-builtins-base.def
b/gcc/config/aarch64/aarch64-neon-builtins-base.def
index 73e86b978d6..db757866906 100644
--- a/gcc/config/aarch64/aarch64-neon-builtins-base.def
+++ b/gcc/config/aarch64/aarch64-neon-builtins-base.def
@@ -610,6 +610,14 @@ DEF_NEON_FUNCTION_GS (vluti4q_laneq, neon_luti2_h, x2,
("Q0,Q0x2,Qu8,ss32", rang
DEF_NEON_FUNCTION_GS (vld1, all_neon, x1234, ("D0xt,al"))
DEF_NEON_FUNCTION_GS (vld1q, all_neon, x1234, ("Q0xt,al"))
DEF_NEON_FUNCTION (vldrq, p128, ("s0,al"))
+
+// Load interleaved tuples
+DEF_NEON_FUNCTION (vld2, all_neon, ("D0x2,al"))
+DEF_NEON_FUNCTION (vld2q, all_neon, ("Q0x2,al"))
+DEF_NEON_FUNCTION (vld3, all_neon, ("D0x3,al"))
+DEF_NEON_FUNCTION (vld3q, all_neon, ("Q0x3,al"))
+DEF_NEON_FUNCTION (vld4, all_neon, ("D0x4,al"))
+DEF_NEON_FUNCTION (vld4q, all_neon, ("Q0x4,al"))
#undef REQUIRED_EXTENSIONS
// Stores
@@ -618,6 +626,14 @@ DEF_NEON_FUNCTION (vldrq, p128, ("s0,al"))
DEF_NEON_FUNCTION_GS (vst1, all_neon, x1234, ("_,as,D0xt"))
DEF_NEON_FUNCTION_GS (vst1q, all_neon, x1234, ("_,as,Q0xt"))
DEF_NEON_FUNCTION (vstrq, p128, ("_,as,s0"))
+
+// Store interleaved tuples
+DEF_NEON_FUNCTION (vst2, all_neon, ("_,as,D0x2"))
+DEF_NEON_FUNCTION (vst2q, all_neon, ("_,as,Q0x2"))
+DEF_NEON_FUNCTION (vst3, all_neon, ("_,as,D0x3"))
+DEF_NEON_FUNCTION (vst3q, all_neon, ("_,as,Q0x3"))
+DEF_NEON_FUNCTION (vst4, all_neon, ("_,as,D0x4"))
+DEF_NEON_FUNCTION (vst4q, all_neon, ("_,as,Q0x4"))
#undef REQUIRED_EXTENSIONS
// AES
diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def
b/gcc/config/aarch64/aarch64-simd-builtins.def
index 9c772321bbd..c75d3d48a90 100644
--- a/gcc/config/aarch64/aarch64-simd-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-builtins.def
@@ -67,28 +67,6 @@
BUILTIN_VSDQ_I (BINOP_SSU, suqadd, 0, DEFAULT)
BUILTIN_VSDQ_I (BINOP_UUS, usqadd, 0, DEFAULT)
- /* Implemented by aarch64_ld<nregs><vstruct_elt>. */
- BUILTIN_VALLDIF (LOADSTRUCT, ld2, 0, LOAD)
- BUILTIN_VSDQ_I_DI (LOADSTRUCT_U, ld2, 0, LOAD)
- BUILTIN_VALLP (LOADSTRUCT_P, ld2, 0, LOAD)
- BUILTIN_VALLDIF (LOADSTRUCT, ld3, 0, LOAD)
- BUILTIN_VSDQ_I_DI (LOADSTRUCT_U, ld3, 0, LOAD)
- BUILTIN_VALLP (LOADSTRUCT_P, ld3, 0, LOAD)
- BUILTIN_VALLDIF (LOADSTRUCT, ld4, 0, LOAD)
- BUILTIN_VSDQ_I_DI (LOADSTRUCT_U, ld4, 0, LOAD)
- BUILTIN_VALLP (LOADSTRUCT_P, ld4, 0, LOAD)
-
- /* Implemented by aarch64_st<nregs><vstruct_elt>. */
- BUILTIN_VALLDIF (STORESTRUCT, st2, 0, STORE)
- BUILTIN_VSDQ_I_DI (STORESTRUCT_U, st2, 0, STORE)
- BUILTIN_VALLP (STORESTRUCT_P, st2, 0, STORE)
- BUILTIN_VALLDIF (STORESTRUCT, st3, 0, STORE)
- BUILTIN_VSDQ_I_DI (STORESTRUCT_U, st3, 0, STORE)
- BUILTIN_VALLP (STORESTRUCT_P, st3, 0, STORE)
- BUILTIN_VALLDIF (STORESTRUCT, st4, 0, STORE)
- BUILTIN_VSDQ_I_DI (STORESTRUCT_U, st4, 0, STORE)
- BUILTIN_VALLP (STORESTRUCT_P, st4, 0, STORE)
-
/* Implemented by aarch64_ld<nregs>r<vstruct_elt>. */
BUILTIN_VALLDIF (LOADSTRUCT, ld2r, 0, LOAD)
BUILTIN_VSDQ_I_DI (LOADSTRUCT_U, ld2r, 0, LOAD)
diff --git a/gcc/config/aarch64/aarch64-simd-pragma-builtins.def
b/gcc/config/aarch64/aarch64-simd-pragma-builtins.def
index e5b807613bd..abd2f80862c 100644
--- a/gcc/config/aarch64/aarch64-simd-pragma-builtins.def
+++ b/gcc/config/aarch64/aarch64-simd-pragma-builtins.def
@@ -165,8 +165,6 @@ ENTRY_LOAD_LANE (vld1q_lane_mf8, mf8q,
mf8_scalar_const_ptr, mf8q,
// ld<n>
#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
-ENTRY_LOAD (vld2_mf8, mf8x2, mf8_scalar_const_ptr, UNSPEC_LD2)
-ENTRY_LOAD (vld2q_mf8, mf8qx2, mf8_scalar_const_ptr, UNSPEC_LD2)
ENTRY_LOAD (vld2_dup_mf8, mf8x2, mf8_scalar_const_ptr, UNSPEC_LD2_DUP)
ENTRY_LOAD (vld2q_dup_mf8, mf8qx2, mf8_scalar_const_ptr, UNSPEC_LD2_DUP)
ENTRY_LOAD_LANE (vld2_lane_mf8, mf8x2, mf8_scalar_const_ptr, mf8x2,
@@ -174,8 +172,6 @@ ENTRY_LOAD_LANE (vld2_lane_mf8, mf8x2,
mf8_scalar_const_ptr, mf8x2,
ENTRY_LOAD_LANE (vld2q_lane_mf8, mf8qx2, mf8_scalar_const_ptr, mf8qx2,
UNSPEC_LD2_LANE)
-ENTRY_LOAD (vld3_mf8, mf8x3, mf8_scalar_const_ptr, UNSPEC_LD3)
-ENTRY_LOAD (vld3q_mf8, mf8qx3, mf8_scalar_const_ptr, UNSPEC_LD3)
ENTRY_LOAD (vld3_dup_mf8, mf8x3, mf8_scalar_const_ptr, UNSPEC_LD3_DUP)
ENTRY_LOAD (vld3q_dup_mf8, mf8qx3, mf8_scalar_const_ptr, UNSPEC_LD3_DUP)
ENTRY_LOAD_LANE (vld3_lane_mf8, mf8x3, mf8_scalar_const_ptr, mf8x3,
@@ -183,8 +179,6 @@ ENTRY_LOAD_LANE (vld3_lane_mf8, mf8x3,
mf8_scalar_const_ptr, mf8x3,
ENTRY_LOAD_LANE (vld3q_lane_mf8, mf8qx3, mf8_scalar_const_ptr, mf8qx3,
UNSPEC_LD3_LANE)
-ENTRY_LOAD (vld4_mf8, mf8x4, mf8_scalar_const_ptr, UNSPEC_LD4)
-ENTRY_LOAD (vld4q_mf8, mf8qx4, mf8_scalar_const_ptr, UNSPEC_LD4)
ENTRY_LOAD (vld4_dup_mf8, mf8x4, mf8_scalar_const_ptr, UNSPEC_LD4_DUP)
ENTRY_LOAD (vld4q_dup_mf8, mf8qx4, mf8_scalar_const_ptr, UNSPEC_LD4_DUP)
ENTRY_LOAD_LANE (vld4_lane_mf8, mf8x4, mf8_scalar_const_ptr, mf8x4,
@@ -211,18 +205,12 @@ ENTRY_STORE_LANE (vst1q_lane_mf8, mf8_scalar_ptr, mf8q,
UNSPEC_ST1_LANE)
// st<n>
#define REQUIRED_EXTENSIONS nonstreaming_only (AARCH64_FL_SIMD)
-ENTRY_STORE (vst2_mf8, mf8_scalar_ptr, mf8x2, UNSPEC_ST2)
-ENTRY_STORE (vst2q_mf8, mf8_scalar_ptr, mf8qx2, UNSPEC_ST2)
ENTRY_STORE_LANE (vst2_lane_mf8, mf8_scalar_ptr, mf8x2, UNSPEC_ST2_LANE)
ENTRY_STORE_LANE (vst2q_lane_mf8, mf8_scalar_ptr, mf8qx2, UNSPEC_ST2_LANE)
-ENTRY_STORE (vst3_mf8, mf8_scalar_ptr, mf8x3, UNSPEC_ST3)
-ENTRY_STORE (vst3q_mf8, mf8_scalar_ptr, mf8qx3, UNSPEC_ST3)
ENTRY_STORE_LANE (vst3_lane_mf8, mf8_scalar_ptr, mf8x3, UNSPEC_ST3_LANE)
ENTRY_STORE_LANE (vst3q_lane_mf8, mf8_scalar_ptr, mf8qx3, UNSPEC_ST3_LANE)
-ENTRY_STORE (vst4_mf8, mf8_scalar_ptr, mf8x4, UNSPEC_ST4)
-ENTRY_STORE (vst4q_mf8, mf8_scalar_ptr, mf8qx4, UNSPEC_ST4)
ENTRY_STORE_LANE (vst4_lane_mf8, mf8_scalar_ptr, mf8x4, UNSPEC_ST4_LANE)
ENTRY_STORE_LANE (vst4q_lane_mf8, mf8_scalar_ptr, mf8qx4, UNSPEC_ST4_LANE)
#undef REQUIRED_EXTENSIONS
diff --git a/gcc/config/aarch64/aarch64-simd.md
b/gcc/config/aarch64/aarch64-simd.md
index 84157be320f..8e80f5d3fa0 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -8407,16 +8407,6 @@ (define_insn "*sqrt<mode>2<vczle><vczbe>"
;; Patterns for vector struct loads and stores.
-(define_insn "aarch64_simd_ld2<vstruct_elt>"
- [(set (match_operand:VSTRUCT_2Q 0 "register_operand" "=w")
- (unspec:VSTRUCT_2Q [
- (match_operand:VSTRUCT_2Q 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD2))]
- "TARGET_SIMD"
- "ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
- [(set_attr "type" "neon_load2_2reg<q>")]
-)
-
(define_insn "@aarch64_simd_ld2r<vstruct_elt>"
[(set (match_operand:VSTRUCT_2QD 0 "register_operand" "=w")
(unspec:VSTRUCT_2QD [
@@ -8443,36 +8433,6 @@ (define_insn
"@aarch64_vec_load_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_load2_one_lane")]
)
-(define_expand "vec_load_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_2Q 0 "register_operand")
- (unspec:VSTRUCT_2Q [
- (match_operand:VSTRUCT_2Q 1 "aarch64_simd_struct_operand")]
- UNSPEC_LD2))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_simd_ld2<vstruct_elt> (tmp, operands[1]));
- emit_insn (gen_aarch64_rev_reglist<mode> (operands[0], tmp, mask));
- }
- else
- emit_insn (gen_aarch64_simd_ld2<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "aarch64_simd_st2<vstruct_elt>"
- [(set (match_operand:VSTRUCT_2Q 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_2Q [
- (match_operand:VSTRUCT_2Q 1 "register_operand" "w")]
- UNSPEC_ST2))]
- "TARGET_SIMD"
- "st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
- [(set_attr "type" "neon_store2_2reg<q>")]
-)
-
;; RTL uses GCC vector extension indices, so flip only for assembly.
(define_insn "aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set (match_operand:BLK 0 "aarch64_simd_struct_operand" "=Utv")
@@ -8488,35 +8448,6 @@ (define_insn
"aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_store2_one_lane<q>")]
)
-(define_expand "vec_store_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_2Q 0 "aarch64_simd_struct_operand")
- (unspec:VSTRUCT_2Q [(match_operand:VSTRUCT_2Q 1 "register_operand")]
- UNSPEC_ST2))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_rev_reglist<mode> (tmp, operands[1], mask));
- emit_insn (gen_aarch64_simd_st2<vstruct_elt> (operands[0], tmp));
- }
- else
- emit_insn (gen_aarch64_simd_st2<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "aarch64_simd_ld3<vstruct_elt>"
- [(set (match_operand:VSTRUCT_3Q 0 "register_operand" "=w")
- (unspec:VSTRUCT_3Q [
- (match_operand:VSTRUCT_3Q 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD3))]
- "TARGET_SIMD"
- "ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
- [(set_attr "type" "neon_load3_3reg<q>")]
-)
-
(define_insn "@aarch64_simd_ld3r<vstruct_elt>"
[(set (match_operand:VSTRUCT_3QD 0 "register_operand" "=w")
(unspec:VSTRUCT_3QD [
@@ -8543,35 +8474,6 @@ (define_insn
"aarch64_vec_load_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_load3_one_lane")]
)
-(define_expand "vec_load_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_3Q 0 "register_operand")
- (unspec:VSTRUCT_3Q [
- (match_operand:VSTRUCT_3Q 1 "aarch64_simd_struct_operand")]
- UNSPEC_LD3))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_simd_ld3<vstruct_elt> (tmp, operands[1]));
- emit_insn (gen_aarch64_rev_reglist<mode> (operands[0], tmp, mask));
- }
- else
- emit_insn (gen_aarch64_simd_ld3<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "aarch64_simd_st3<vstruct_elt>"
- [(set (match_operand:VSTRUCT_3Q 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_3Q [(match_operand:VSTRUCT_3Q 1 "register_operand" "w")]
- UNSPEC_ST3))]
- "TARGET_SIMD"
- "st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
- [(set_attr "type" "neon_store3_3reg<q>")]
-)
-
;; RTL uses GCC vector extension indices, so flip only for assembly.
(define_insn "aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set (match_operand:BLK 0 "aarch64_simd_struct_operand" "=Utv")
@@ -8587,36 +8489,6 @@ (define_insn
"aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_store3_one_lane<q>")]
)
-(define_expand "vec_store_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_3Q 0 "aarch64_simd_struct_operand")
- (unspec:VSTRUCT_3Q [
- (match_operand:VSTRUCT_3Q 1 "register_operand")]
- UNSPEC_ST3))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_rev_reglist<mode> (tmp, operands[1], mask));
- emit_insn (gen_aarch64_simd_st3<vstruct_elt> (operands[0], tmp));
- }
- else
- emit_insn (gen_aarch64_simd_st3<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "aarch64_simd_ld4<vstruct_elt>"
- [(set (match_operand:VSTRUCT_4Q 0 "register_operand" "=w")
- (unspec:VSTRUCT_4Q [
- (match_operand:VSTRUCT_4Q 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD4))]
- "TARGET_SIMD"
- "ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
- [(set_attr "type" "neon_load4_4reg<q>")]
-)
-
(define_insn "@aarch64_simd_ld4r<vstruct_elt>"
[(set (match_operand:VSTRUCT_4QD 0 "register_operand" "=w")
(unspec:VSTRUCT_4QD [
@@ -8643,36 +8515,6 @@ (define_insn
"aarch64_vec_load_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_load4_one_lane")]
)
-(define_expand "vec_load_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_4Q 0 "register_operand")
- (unspec:VSTRUCT_4Q [
- (match_operand:VSTRUCT_4Q 1 "aarch64_simd_struct_operand")]
- UNSPEC_LD4))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_simd_ld4<vstruct_elt> (tmp, operands[1]));
- emit_insn (gen_aarch64_rev_reglist<mode> (operands[0], tmp, mask));
- }
- else
- emit_insn (gen_aarch64_simd_ld4<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
-(define_insn "aarch64_simd_st4<vstruct_elt>"
- [(set (match_operand:VSTRUCT_4Q 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_4Q [
- (match_operand:VSTRUCT_4Q 1 "register_operand" "w")]
- UNSPEC_ST4))]
- "TARGET_SIMD"
- "st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
- [(set_attr "type" "neon_store4_4reg<q>")]
-)
-
;; RTL uses GCC vector extension indices, so flip only for assembly.
(define_insn "aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set (match_operand:BLK 0 "aarch64_simd_struct_operand" "=Utv")
@@ -8688,25 +8530,6 @@ (define_insn
"aarch64_vec_store_lanes<mode>_lane<vstruct_elt>"
[(set_attr "type" "neon_store4_one_lane<q>")]
)
-(define_expand "vec_store_lanes<mode><vstruct_elt>"
- [(set (match_operand:VSTRUCT_4Q 0 "aarch64_simd_struct_operand")
- (unspec:VSTRUCT_4Q [(match_operand:VSTRUCT_4Q 1 "register_operand")]
- UNSPEC_ST4))]
- "TARGET_SIMD"
-{
- if (BYTES_BIG_ENDIAN)
- {
- rtx tmp = gen_reg_rtx (<MODE>mode);
- rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
- GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
- emit_insn (gen_aarch64_rev_reglist<mode> (tmp, operands[1], mask));
- emit_insn (gen_aarch64_simd_st4<vstruct_elt> (operands[0], tmp));
- }
- else
- emit_insn (gen_aarch64_simd_st4<vstruct_elt> (operands[0], operands[1]));
- DONE;
-})
-
;; Patterns for rcpc3 vector lane loads and stores.
(define_insn "aarch64_vec_stl1_lanes<mode>_lane<Vel>"
@@ -9145,86 +8968,6 @@ (define_expand "aarch64_ld<nregs>r<vstruct_elt>"
DONE;
})
-(define_insn "aarch64_ld2<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_2DNX 0 "register_operand" "=w")
- (unspec:VSTRUCT_2DNX [
- (match_operand:VSTRUCT_2DNX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD2_DREG))]
- "TARGET_SIMD"
- "ld2\\t{%S0.<Vtype> - %T0.<Vtype>}, %1"
- [(set_attr "type" "neon_load2_2reg<q>")]
-)
-
-(define_insn "aarch64_ld2<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_2DX 0 "register_operand" "=w")
- (unspec:VSTRUCT_2DX [
- (match_operand:VSTRUCT_2DX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD2_DREG))]
- "TARGET_SIMD"
- "ld1\\t{%S0.1d - %T0.1d}, %1"
- [(set_attr "type" "neon_load1_2reg<q>")]
-)
-
-(define_insn "aarch64_ld3<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_3DNX 0 "register_operand" "=w")
- (unspec:VSTRUCT_3DNX [
- (match_operand:VSTRUCT_3DNX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD3_DREG))]
- "TARGET_SIMD"
- "ld3\\t{%S0.<Vtype> - %U0.<Vtype>}, %1"
- [(set_attr "type" "neon_load3_3reg<q>")]
-)
-
-(define_insn "aarch64_ld3<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_3DX 0 "register_operand" "=w")
- (unspec:VSTRUCT_3DX [
- (match_operand:VSTRUCT_3DX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD3_DREG))]
- "TARGET_SIMD"
- "ld1\\t{%S0.1d - %U0.1d}, %1"
- [(set_attr "type" "neon_load1_3reg<q>")]
-)
-
-(define_insn "aarch64_ld4<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_4DNX 0 "register_operand" "=w")
- (unspec:VSTRUCT_4DNX [
- (match_operand:VSTRUCT_4DNX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD4_DREG))]
- "TARGET_SIMD"
- "ld4\\t{%S0.<Vtype> - %V0.<Vtype>}, %1"
- [(set_attr "type" "neon_load4_4reg<q>")]
-)
-
-(define_insn "aarch64_ld4<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_4DX 0 "register_operand" "=w")
- (unspec:VSTRUCT_4DX [
- (match_operand:VSTRUCT_4DX 1 "aarch64_simd_struct_operand" "Utv")]
- UNSPEC_LD4_DREG))]
- "TARGET_SIMD"
- "ld1\\t{%S0.1d - %V0.1d}, %1"
- [(set_attr "type" "neon_load1_4reg<q>")]
-)
-
-(define_expand "@aarch64_ld<nregs><vstruct_elt>"
- [(match_operand:VSTRUCT_D 0 "register_operand")
- (match_operand:DI 1 "register_operand")]
- "TARGET_SIMD"
-{
- rtx mem = gen_rtx_MEM (<MODE>mode, operands[1]);
- emit_insn (gen_aarch64_ld<nregs><vstruct_elt>_dreg (operands[0], mem));
- DONE;
-})
-
-(define_expand "@aarch64_ld<nregs><vstruct_elt>"
- [(match_operand:VSTRUCT_Q 0 "register_operand")
- (match_operand:DI 1 "register_operand")]
- "TARGET_SIMD"
-{
- rtx mem = gen_rtx_MEM (<MODE>mode, operands[1]);
- emit_insn (gen_aarch64_simd_ld<nregs><vstruct_elt> (operands[0], mem));
- DONE;
-})
-
(define_expand "@aarch64_ld<nregs>_lane<vstruct_elt>"
[(match_operand:VSTRUCT_QD 0 "register_operand")
(match_operand:DI 1 "register_operand")
@@ -9437,86 +9180,6 @@ (define_insn
"@aarch64_rev<REVERSE:rev_op><mode><vczle><vczbe>"
[(set_attr "type" "neon_rev<q>")]
)
-(define_insn "aarch64_st2<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_2DNX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_2DNX [
- (match_operand:VSTRUCT_2DNX 1 "register_operand" "w")]
- UNSPEC_ST2))]
- "TARGET_SIMD"
- "st2\\t{%S1.<Vtype> - %T1.<Vtype>}, %0"
- [(set_attr "type" "neon_store2_2reg")]
-)
-
-(define_insn "aarch64_st2<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_2DX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_2DX [
- (match_operand:VSTRUCT_2DX 1 "register_operand" "w")]
- UNSPEC_ST2))]
- "TARGET_SIMD"
- "st1\\t{%S1.1d - %T1.1d}, %0"
- [(set_attr "type" "neon_store1_2reg")]
-)
-
-(define_insn "aarch64_st3<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_3DNX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_3DNX [
- (match_operand:VSTRUCT_3DNX 1 "register_operand" "w")]
- UNSPEC_ST3))]
- "TARGET_SIMD"
- "st3\\t{%S1.<Vtype> - %U1.<Vtype>}, %0"
- [(set_attr "type" "neon_store3_3reg")]
-)
-
-(define_insn "aarch64_st3<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_3DX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_3DX [
- (match_operand:VSTRUCT_3DX 1 "register_operand" "w")]
- UNSPEC_ST3))]
- "TARGET_SIMD"
- "st1\\t{%S1.1d - %U1.1d}, %0"
- [(set_attr "type" "neon_store1_3reg")]
-)
-
-(define_insn "aarch64_st4<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_4DNX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_4DNX [
- (match_operand:VSTRUCT_4DNX 1 "register_operand" "w")]
- UNSPEC_ST4))]
- "TARGET_SIMD"
- "st4\\t{%S1.<Vtype> - %V1.<Vtype>}, %0"
- [(set_attr "type" "neon_store4_4reg")]
-)
-
-(define_insn "aarch64_st4<vstruct_elt>_dreg"
- [(set (match_operand:VSTRUCT_4DX 0 "aarch64_simd_struct_operand" "=Utv")
- (unspec:VSTRUCT_4DX [
- (match_operand:VSTRUCT_4DX 1 "register_operand" "w")]
- UNSPEC_ST4))]
- "TARGET_SIMD"
- "st1\\t{%S1.1d - %V1.1d}, %0"
- [(set_attr "type" "neon_store1_4reg")]
-)
-
-(define_expand "@aarch64_st<nregs><vstruct_elt>"
- [(match_operand:DI 0 "register_operand")
- (match_operand:VSTRUCT_D 1 "register_operand")]
- "TARGET_SIMD"
-{
- rtx mem = gen_rtx_MEM (<MODE>mode, operands[0]);
- emit_insn (gen_aarch64_st<nregs><vstruct_elt>_dreg (mem, operands[1]));
- DONE;
-})
-
-(define_expand "@aarch64_st<nregs><vstruct_elt>"
- [(match_operand:DI 0 "register_operand")
- (match_operand:VSTRUCT_Q 1 "register_operand")]
- "TARGET_SIMD"
-{
- rtx mem = gen_rtx_MEM (<MODE>mode, operands[0]);
- emit_insn (gen_aarch64_simd_st<nregs><vstruct_elt> (mem, operands[1]));
- DONE;
-})
-
(define_expand "@aarch64_st<nregs>_lane<vstruct_elt>"
[(match_operand:DI 0 "register_operand")
(match_operand:VSTRUCT_QD 1 "register_operand")
@@ -11114,3 +10777,77 @@ (define_insn "@aarch64_<insn><mode>"
[ w , 0 , w , w ] <insn>\t%0.<Vtype>, %2.16b, %3.16b
}
)
+
+(define_expand "vec_load_lanes<mode><vstruct_elt>"
+ [(set (match_operand:VSTRUCT_INTERLEAVED 0 "register_operand")
+ (unspec:VSTRUCT_INTERLEAVED [
+ (match_operand:VSTRUCT_INTERLEAVED 1
"aarch64_simd_struct_operand")]
+ UNSPEC_LOAD_INTERLEAVED))]
+ "TARGET_SIMD"
+{
+ if (BYTES_BIG_ENDIAN)
+ {
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
+ GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
+ emit_insn (gen_aarch64_load_interleaved<mode> (tmp, operands[1]));
+ emit_insn (gen_aarch64_rev_reglist<mode> (operands[0], tmp, mask));
+ }
+ else
+ emit_insn (gen_aarch64_load_interleaved<mode> (operands[0], operands[1]));
+ DONE;
+})
+(define_insn "@aarch64_load_interleaved<mode>"
+ [(set (match_operand:VSTRUCT_QDNX 0 "register_operand" "=w")
+ (unspec:VSTRUCT_QDNX [
+ (match_operand:VSTRUCT_QDNX 1 "aarch64_simd_struct_operand" "Utv")]
+ UNSPEC_LOAD_INTERLEAVED))]
+ "TARGET_SIMD"
+ {
+ switch (<nregs>)
+ {
+ case 2: return "ld2\t{%S0.<Vtype> - %T0.<Vtype>}, %1";
+ case 3: return "ld3\t{%S0.<Vtype> - %U0.<Vtype>}, %1";
+ case 4: return "ld4\t{%S0.<Vtype> - %V0.<Vtype>}, %1";
+ default: gcc_unreachable();
+ }
+ }
+ [(set_attr "type" "neon_load<nregs>_<nregs>reg<q>")]
+)
+
+(define_expand "vec_store_lanes<mode><vstruct_elt>"
+ [(set (match_operand:VSTRUCT_INTERLEAVED 0 "aarch64_simd_struct_operand")
+ (unspec:VSTRUCT_INTERLEAVED [
+ (match_operand:VSTRUCT_INTERLEAVED 1 "register_operand")]
+ UNSPEC_STORE_INTERLEAVED))]
+ "TARGET_SIMD"
+{
+ if (BYTES_BIG_ENDIAN)
+ {
+ rtx tmp = gen_reg_rtx (<MODE>mode);
+ rtx mask = aarch64_reverse_mask (<VSTRUCT_ELT>mode,
+ GET_MODE_NUNITS (<MODE>mode).to_constant () / <nregs>);
+ emit_insn (gen_aarch64_rev_reglist<mode> (tmp, operands[1], mask));
+ emit_insn (gen_aarch64_store_interleaved<mode> (operands[0], tmp));
+ }
+ else
+ emit_insn (gen_aarch64_store_interleaved<mode> (operands[0], operands[1]));
+ DONE;
+})
+(define_insn "@aarch64_store_interleaved<mode>"
+ [(set (match_operand:VSTRUCT_QDNX 0 "aarch64_simd_struct_operand" "=Utv")
+ (unspec:VSTRUCT_QDNX [
+ (match_operand:VSTRUCT_QDNX 1 "register_operand" "w")]
+ UNSPEC_STORE_INTERLEAVED))]
+ "TARGET_SIMD"
+ {
+ switch (<nregs>)
+ {
+ case 2: return "st2\t{%S1.<Vtype> - %T1.<Vtype>}, %0";
+ case 3: return "st3\t{%S1.<Vtype> - %U1.<Vtype>}, %0";
+ case 4: return "st4\t{%S1.<Vtype> - %V1.<Vtype>}, %0";
+ default: gcc_unreachable();
+ }
+ }
+ [(set_attr "type" "neon_store<nregs>_<nregs>reg<q>")]
+)
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 2b3efe6a022..8541ef088cc 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -267,15 +267,10 @@ (define_c_enum "unspec" [
UNSPEC_LDP_FST
UNSPEC_LDP_SND
UNSPEC_LOAD_MULTIPLE
+ UNSPEC_LOAD_INTERLEAVED
UNSPEC_LD1_DUP
- UNSPEC_LD2
- UNSPEC_LD2_DREG
UNSPEC_LD2_DUP
- UNSPEC_LD3
- UNSPEC_LD3_DREG
UNSPEC_LD3_DUP
- UNSPEC_LD4
- UNSPEC_LD4_DREG
UNSPEC_LD4_DUP
UNSPEC_LD2_LANE
UNSPEC_LD3_LANE
@@ -305,10 +300,8 @@ (define_c_enum "unspec" [
UNSPEC_SISD_USHL
UNSPEC_SSHL_2S
UNSPEC_STORE_MULTIPLE
+ UNSPEC_STORE_INTERLEAVED
UNSPEC_ST1_LANE
- UNSPEC_ST2
- UNSPEC_ST3
- UNSPEC_ST4
UNSPEC_ST2_LANE
UNSPEC_ST3_LANE
UNSPEC_ST4_LANE
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index d995299c68e..69687125a92 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -456,6 +456,8 @@ (define_mode_iterator VSTRUCT_3DNX [V3x8QI V3x4HI V3x2SI
V3x4HF
(define_mode_iterator VSTRUCT_4DNX [V4x8QI V4x4HI V4x2SI V4x4HF
V4x2SF V4x4BF])
+(define_mode_iterator VSTRUCT_DNX [VSTRUCT_2DNX VSTRUCT_3DNX VSTRUCT_4DNX])
+
;; Advanced SIMD 64-bit structure modes with 64-bit elements.
(define_mode_iterator VSTRUCT_DX [V2x1DI V2x1DF V3x1DI V3x1DF V4x1DI V4x1DF])
@@ -496,6 +498,8 @@ (define_mode_iterator VSTRUCT_4QD [VSTRUCT_4D VSTRUCT_4Q])
;; Advanced SIMD vector structure modes.
(define_mode_iterator VSTRUCT_QD [VSTRUCT_D VSTRUCT_Q])
+(define_mode_iterator VSTRUCT_QDNX [VSTRUCT_DNX VSTRUCT_Q])
+(define_mode_iterator VSTRUCT_INTERLEAVED [(VSTRUCT_DNX "!BYTES_BIG_ENDIAN")
VSTRUCT_Q])
;; Double scalar modes
(define_mode_iterator DX [DI DF DD])
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_39.c
b/gcc/testsuite/gcc.dg/vect/vect-early-break_39.c
index bc862ad20e6..6cb2c982a46 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-early-break_39.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_39.c
@@ -8,7 +8,7 @@
#endif
unsigned vect_a[N];
unsigned vect_b[N];
-
+
unsigned test4(unsigned x, unsigned n)
{
unsigned ret = 0;
@@ -18,11 +18,10 @@ unsigned test4(unsigned x, unsigned n)
if (vect_a[i]*2 > x)
break;
vect_a[i] = x;
-
+
}
return ret;
}
-/* AArch64 will scalarize the load and is able to vectorize it. */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 1 "vect"
{ target aarch64*-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 1 "vect"
{ xfail aarch64*-*-* } } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops in function" 0 "vect"
{ target { ! aarch64*-*-* } } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vld2.c
b/gcc/testsuite/gcc.target/aarch64/neon/vld2.c
new file mode 100644
index 00000000000..63a39bfa172
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vld2.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vld2_mf8:
+** ld2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_mf8, mfloat8x8x2_t, const mfloat8_t *)
+
+/*
+** test_vld2_s8:
+** ld2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_s8, int8x8x2_t, const int8_t *)
+
+/*
+** test_vld2_u8:
+** ld2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_u8, uint8x8x2_t, const uint8_t *)
+
+/*
+** test_vld2_s16:
+** ld2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_s16, int16x4x2_t, const int16_t *)
+
+/*
+** test_vld2_u16:
+** ld2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_u16, uint16x4x2_t, const uint16_t *)
+
+/*
+** test_vld2_s32:
+** ld2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_s32, int32x2x2_t, const int32_t *)
+
+/*
+** test_vld2_u32:
+** ld2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_u32, uint32x2x2_t, const uint32_t *)
+
+/*
+** test_vld2_s64:
+** ld1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_s64, int64x1x2_t, const int64_t *)
+
+/*
+** test_vld2_u64:
+** ld1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_u64, uint64x1x2_t, const uint64_t *)
+
+/*
+** test_vld2_p8:
+** ld2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_p8, poly8x8x2_t, const poly8_t *)
+
+/*
+** test_vld2_p16:
+** ld2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_p16, poly16x4x2_t, const poly16_t *)
+
+/*
+** test_vld2_p64:
+** ld1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_p64, poly64x1x2_t, const poly64_t *)
+
+/*
+** test_vld2_bf16:
+** ld2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_bf16, bfloat16x4x2_t, const bfloat16_t *)
+
+/*
+** test_vld2_f16:
+** ld2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_f16, float16x4x2_t, const float16_t *)
+
+/*
+** test_vld2_f32:
+** ld2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_f32, float32x2x2_t, const float32_t *)
+
+/*
+** test_vld2_f64:
+** ld1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2_f64, float64x1x2_t, const float64_t *)
+
+/*
+** test_vld2q_mf8:
+** ld2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_mf8, mfloat8x16x2_t, const mfloat8_t *)
+
+/*
+** test_vld2q_s8:
+** ld2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_s8, int8x16x2_t, const int8_t *)
+
+/*
+** test_vld2q_u8:
+** ld2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_u8, uint8x16x2_t, const uint8_t *)
+
+/*
+** test_vld2q_s16:
+** ld2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_s16, int16x8x2_t, const int16_t *)
+
+/*
+** test_vld2q_u16:
+** ld2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_u16, uint16x8x2_t, const uint16_t *)
+
+/*
+** test_vld2q_s32:
+** ld2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_s32, int32x4x2_t, const int32_t *)
+
+/*
+** test_vld2q_u32:
+** ld2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_u32, uint32x4x2_t, const uint32_t *)
+
+/*
+** test_vld2q_s64:
+** ld2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_s64, int64x2x2_t, const int64_t *)
+
+/*
+** test_vld2q_u64:
+** ld2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_u64, uint64x2x2_t, const uint64_t *)
+
+/*
+** test_vld2q_p8:
+** ld2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_p8, poly8x16x2_t, const poly8_t *)
+
+/*
+** test_vld2q_p16:
+** ld2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_p16, poly16x8x2_t, const poly16_t *)
+
+/*
+** test_vld2q_p64:
+** ld2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_p64, poly64x2x2_t, const poly64_t *)
+
+/*
+** test_vld2q_bf16:
+** ld2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_bf16, bfloat16x8x2_t, const bfloat16_t *)
+
+/*
+** test_vld2q_f16:
+** ld2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_f16, float16x8x2_t, const float16_t *)
+
+/*
+** test_vld2q_f32:
+** ld2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_f32, float32x4x2_t, const float32_t *)
+
+/*
+** test_vld2q_f64:
+** ld2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld2q_f64, float64x2x2_t, const float64_t *)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vld3.c
b/gcc/testsuite/gcc.target/aarch64/neon/vld3.c
new file mode 100644
index 00000000000..9dda6ec5471
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vld3.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vld3_mf8:
+** ld3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_mf8, mfloat8x8x3_t, const mfloat8_t *)
+
+/*
+** test_vld3_s8:
+** ld3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_s8, int8x8x3_t, const int8_t *)
+
+/*
+** test_vld3_u8:
+** ld3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_u8, uint8x8x3_t, const uint8_t *)
+
+/*
+** test_vld3_s16:
+** ld3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_s16, int16x4x3_t, const int16_t *)
+
+/*
+** test_vld3_u16:
+** ld3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_u16, uint16x4x3_t, const uint16_t *)
+
+/*
+** test_vld3_s32:
+** ld3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_s32, int32x2x3_t, const int32_t *)
+
+/*
+** test_vld3_u32:
+** ld3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_u32, uint32x2x3_t, const uint32_t *)
+
+/*
+** test_vld3_s64:
+** ld1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_s64, int64x1x3_t, const int64_t *)
+
+/*
+** test_vld3_u64:
+** ld1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_u64, uint64x1x3_t, const uint64_t *)
+
+/*
+** test_vld3_p8:
+** ld3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_p8, poly8x8x3_t, const poly8_t *)
+
+/*
+** test_vld3_p16:
+** ld3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_p16, poly16x4x3_t, const poly16_t *)
+
+/*
+** test_vld3_p64:
+** ld1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_p64, poly64x1x3_t, const poly64_t *)
+
+/*
+** test_vld3_bf16:
+** ld3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_bf16, bfloat16x4x3_t, const bfloat16_t *)
+
+/*
+** test_vld3_f16:
+** ld3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_f16, float16x4x3_t, const float16_t *)
+
+/*
+** test_vld3_f32:
+** ld3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_f32, float32x2x3_t, const float32_t *)
+
+/*
+** test_vld3_f64:
+** ld1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3_f64, float64x1x3_t, const float64_t *)
+
+/*
+** test_vld3q_mf8:
+** ld3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_mf8, mfloat8x16x3_t, const mfloat8_t *)
+
+/*
+** test_vld3q_s8:
+** ld3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_s8, int8x16x3_t, const int8_t *)
+
+/*
+** test_vld3q_u8:
+** ld3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_u8, uint8x16x3_t, const uint8_t *)
+
+/*
+** test_vld3q_s16:
+** ld3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_s16, int16x8x3_t, const int16_t *)
+
+/*
+** test_vld3q_u16:
+** ld3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_u16, uint16x8x3_t, const uint16_t *)
+
+/*
+** test_vld3q_s32:
+** ld3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_s32, int32x4x3_t, const int32_t *)
+
+/*
+** test_vld3q_u32:
+** ld3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_u32, uint32x4x3_t, const uint32_t *)
+
+/*
+** test_vld3q_s64:
+** ld3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_s64, int64x2x3_t, const int64_t *)
+
+/*
+** test_vld3q_u64:
+** ld3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_u64, uint64x2x3_t, const uint64_t *)
+
+/*
+** test_vld3q_p8:
+** ld3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_p8, poly8x16x3_t, const poly8_t *)
+
+/*
+** test_vld3q_p16:
+** ld3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_p16, poly16x8x3_t, const poly16_t *)
+
+/*
+** test_vld3q_p64:
+** ld3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_p64, poly64x2x3_t, const poly64_t *)
+
+/*
+** test_vld3q_bf16:
+** ld3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_bf16, bfloat16x8x3_t, const bfloat16_t *)
+
+/*
+** test_vld3q_f16:
+** ld3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_f16, float16x8x3_t, const float16_t *)
+
+/*
+** test_vld3q_f32:
+** ld3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_f32, float32x4x3_t, const float32_t *)
+
+/*
+** test_vld3q_f64:
+** ld3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld3q_f64, float64x2x3_t, const float64_t *)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vld4.c
b/gcc/testsuite/gcc.target/aarch64/neon/vld4.c
new file mode 100644
index 00000000000..b8ff70f3474
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vld4.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vld4_mf8:
+** ld4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_mf8, mfloat8x8x4_t, const mfloat8_t *)
+
+/*
+** test_vld4_s8:
+** ld4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_s8, int8x8x4_t, const int8_t *)
+
+/*
+** test_vld4_u8:
+** ld4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_u8, uint8x8x4_t, const uint8_t *)
+
+/*
+** test_vld4_s16:
+** ld4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_s16, int16x4x4_t, const int16_t *)
+
+/*
+** test_vld4_u16:
+** ld4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_u16, uint16x4x4_t, const uint16_t *)
+
+/*
+** test_vld4_s32:
+** ld4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_s32, int32x2x4_t, const int32_t *)
+
+/*
+** test_vld4_u32:
+** ld4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_u32, uint32x2x4_t, const uint32_t *)
+
+/*
+** test_vld4_s64:
+** ld1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_s64, int64x1x4_t, const int64_t *)
+
+/*
+** test_vld4_u64:
+** ld1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_u64, uint64x1x4_t, const uint64_t *)
+
+/*
+** test_vld4_p8:
+** ld4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_p8, poly8x8x4_t, const poly8_t *)
+
+/*
+** test_vld4_p16:
+** ld4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_p16, poly16x4x4_t, const poly16_t *)
+
+/*
+** test_vld4_p64:
+** ld1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_p64, poly64x1x4_t, const poly64_t *)
+
+/*
+** test_vld4_bf16:
+** ld4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_bf16, bfloat16x4x4_t, const bfloat16_t *)
+
+/*
+** test_vld4_f16:
+** ld4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_f16, float16x4x4_t, const float16_t *)
+
+/*
+** test_vld4_f32:
+** ld4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_f32, float32x2x4_t, const float32_t *)
+
+/*
+** test_vld4_f64:
+** ld1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4_f64, float64x1x4_t, const float64_t *)
+
+/*
+** test_vld4q_mf8:
+** ld4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_mf8, mfloat8x16x4_t, const mfloat8_t *)
+
+/*
+** test_vld4q_s8:
+** ld4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_s8, int8x16x4_t, const int8_t *)
+
+/*
+** test_vld4q_u8:
+** ld4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_u8, uint8x16x4_t, const uint8_t *)
+
+/*
+** test_vld4q_s16:
+** ld4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_s16, int16x8x4_t, const int16_t *)
+
+/*
+** test_vld4q_u16:
+** ld4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_u16, uint16x8x4_t, const uint16_t *)
+
+/*
+** test_vld4q_s32:
+** ld4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_s32, int32x4x4_t, const int32_t *)
+
+/*
+** test_vld4q_u32:
+** ld4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_u32, uint32x4x4_t, const uint32_t *)
+
+/*
+** test_vld4q_s64:
+** ld4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_s64, int64x2x4_t, const int64_t *)
+
+/*
+** test_vld4q_u64:
+** ld4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_u64, uint64x2x4_t, const uint64_t *)
+
+/*
+** test_vld4q_p8:
+** ld4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_p8, poly8x16x4_t, const poly8_t *)
+
+/*
+** test_vld4q_p16:
+** ld4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_p16, poly16x8x4_t, const poly16_t *)
+
+/*
+** test_vld4q_p64:
+** ld4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_p64, poly64x2x4_t, const poly64_t *)
+
+/*
+** test_vld4q_bf16:
+** ld4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_bf16, bfloat16x8x4_t, const bfloat16_t *)
+
+/*
+** test_vld4q_f16:
+** ld4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_f16, float16x8x4_t, const float16_t *)
+
+/*
+** test_vld4q_f32:
+** ld4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_f32, float32x4x4_t, const float32_t *)
+
+/*
+** test_vld4q_f64:
+** ld4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_UNARY (vld4q_f64, float64x2x4_t, const float64_t *)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vst2.c
b/gcc/testsuite/gcc.target/aarch64/neon/vst2.c
new file mode 100644
index 00000000000..1fa33f49d41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vst2.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vst2_mf8:
+** st2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_mf8, mfloat8_t *, mfloat8x8x2_t)
+
+/*
+** test_vst2_s8:
+** st2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_s8, int8_t *, int8x8x2_t)
+
+/*
+** test_vst2_u8:
+** st2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_u8, uint8_t *, uint8x8x2_t)
+
+/*
+** test_vst2_s16:
+** st2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_s16, int16_t *, int16x4x2_t)
+
+/*
+** test_vst2_u16:
+** st2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_u16, uint16_t *, uint16x4x2_t)
+
+/*
+** test_vst2_s32:
+** st2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_s32, int32_t *, int32x2x2_t)
+
+/*
+** test_vst2_u32:
+** st2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_u32, uint32_t *, uint32x2x2_t)
+
+/*
+** test_vst2_s64:
+** st1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_s64, int64_t *, int64x1x2_t)
+
+/*
+** test_vst2_u64:
+** st1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_u64, uint64_t *, uint64x1x2_t)
+
+/*
+** test_vst2_p8:
+** st2 {v0\.8b - v1\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_p8, poly8_t *, poly8x8x2_t)
+
+/*
+** test_vst2_p16:
+** st2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_p16, poly16_t *, poly16x4x2_t)
+
+/*
+** test_vst2_p64:
+** st1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_p64, poly64_t *, poly64x1x2_t)
+
+/*
+** test_vst2_bf16:
+** st2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_bf16, bfloat16_t *, bfloat16x4x2_t)
+
+/*
+** test_vst2_f16:
+** st2 {v0\.4h - v1\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_f16, float16_t *, float16x4x2_t)
+
+/*
+** test_vst2_f32:
+** st2 {v0\.2s - v1\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_f32, float32_t *, float32x2x2_t)
+
+/*
+** test_vst2_f64:
+** st1 {v0\.1d - v1\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2_f64, float64_t *, float64x1x2_t)
+
+/*
+** test_vst2q_mf8:
+** st2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_mf8, mfloat8_t *, mfloat8x16x2_t)
+
+/*
+** test_vst2q_s8:
+** st2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_s8, int8_t *, int8x16x2_t)
+
+/*
+** test_vst2q_u8:
+** st2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_u8, uint8_t *, uint8x16x2_t)
+
+/*
+** test_vst2q_s16:
+** st2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_s16, int16_t *, int16x8x2_t)
+
+/*
+** test_vst2q_u16:
+** st2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_u16, uint16_t *, uint16x8x2_t)
+
+/*
+** test_vst2q_s32:
+** st2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_s32, int32_t *, int32x4x2_t)
+
+/*
+** test_vst2q_u32:
+** st2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_u32, uint32_t *, uint32x4x2_t)
+
+/*
+** test_vst2q_s64:
+** st2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_s64, int64_t *, int64x2x2_t)
+
+/*
+** test_vst2q_u64:
+** st2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_u64, uint64_t *, uint64x2x2_t)
+
+/*
+** test_vst2q_p8:
+** st2 {v0\.16b - v1\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_p8, poly8_t *, poly8x16x2_t)
+
+/*
+** test_vst2q_p16:
+** st2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_p16, poly16_t *, poly16x8x2_t)
+
+/*
+** test_vst2q_p64:
+** st2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_p64, poly64_t *, poly64x2x2_t)
+
+/*
+** test_vst2q_bf16:
+** st2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_bf16, bfloat16_t *, bfloat16x8x2_t)
+
+/*
+** test_vst2q_f16:
+** st2 {v0\.8h - v1\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_f16, float16_t *, float16x8x2_t)
+
+/*
+** test_vst2q_f32:
+** st2 {v0\.4s - v1\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_f32, float32_t *, float32x4x2_t)
+
+/*
+** test_vst2q_f64:
+** st2 {v0\.2d - v1\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst2q_f64, float64_t *, float64x2x2_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vst3.c
b/gcc/testsuite/gcc.target/aarch64/neon/vst3.c
new file mode 100644
index 00000000000..1084efda274
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vst3.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vst3_mf8:
+** st3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_mf8, mfloat8_t *, mfloat8x8x3_t)
+
+/*
+** test_vst3_s8:
+** st3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_s8, int8_t *, int8x8x3_t)
+
+/*
+** test_vst3_u8:
+** st3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_u8, uint8_t *, uint8x8x3_t)
+
+/*
+** test_vst3_s16:
+** st3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_s16, int16_t *, int16x4x3_t)
+
+/*
+** test_vst3_u16:
+** st3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_u16, uint16_t *, uint16x4x3_t)
+
+/*
+** test_vst3_s32:
+** st3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_s32, int32_t *, int32x2x3_t)
+
+/*
+** test_vst3_u32:
+** st3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_u32, uint32_t *, uint32x2x3_t)
+
+/*
+** test_vst3_s64:
+** st1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_s64, int64_t *, int64x1x3_t)
+
+/*
+** test_vst3_u64:
+** st1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_u64, uint64_t *, uint64x1x3_t)
+
+/*
+** test_vst3_p8:
+** st3 {v0\.8b - v2\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_p8, poly8_t *, poly8x8x3_t)
+
+/*
+** test_vst3_p16:
+** st3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_p16, poly16_t *, poly16x4x3_t)
+
+/*
+** test_vst3_p64:
+** st1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_p64, poly64_t *, poly64x1x3_t)
+
+/*
+** test_vst3_bf16:
+** st3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_bf16, bfloat16_t *, bfloat16x4x3_t)
+
+/*
+** test_vst3_f16:
+** st3 {v0\.4h - v2\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_f16, float16_t *, float16x4x3_t)
+
+/*
+** test_vst3_f32:
+** st3 {v0\.2s - v2\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_f32, float32_t *, float32x2x3_t)
+
+/*
+** test_vst3_f64:
+** st1 {v0\.1d - v2\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3_f64, float64_t *, float64x1x3_t)
+
+/*
+** test_vst3q_mf8:
+** st3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_mf8, mfloat8_t *, mfloat8x16x3_t)
+
+/*
+** test_vst3q_s8:
+** st3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_s8, int8_t *, int8x16x3_t)
+
+/*
+** test_vst3q_u8:
+** st3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_u8, uint8_t *, uint8x16x3_t)
+
+/*
+** test_vst3q_s16:
+** st3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_s16, int16_t *, int16x8x3_t)
+
+/*
+** test_vst3q_u16:
+** st3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_u16, uint16_t *, uint16x8x3_t)
+
+/*
+** test_vst3q_s32:
+** st3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_s32, int32_t *, int32x4x3_t)
+
+/*
+** test_vst3q_u32:
+** st3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_u32, uint32_t *, uint32x4x3_t)
+
+/*
+** test_vst3q_s64:
+** st3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_s64, int64_t *, int64x2x3_t)
+
+/*
+** test_vst3q_u64:
+** st3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_u64, uint64_t *, uint64x2x3_t)
+
+/*
+** test_vst3q_p8:
+** st3 {v0\.16b - v2\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_p8, poly8_t *, poly8x16x3_t)
+
+/*
+** test_vst3q_p16:
+** st3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_p16, poly16_t *, poly16x8x3_t)
+
+/*
+** test_vst3q_p64:
+** st3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_p64, poly64_t *, poly64x2x3_t)
+
+/*
+** test_vst3q_bf16:
+** st3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_bf16, bfloat16_t *, bfloat16x8x3_t)
+
+/*
+** test_vst3q_f16:
+** st3 {v0\.8h - v2\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_f16, float16_t *, float16x8x3_t)
+
+/*
+** test_vst3q_f32:
+** st3 {v0\.4s - v2\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_f32, float32_t *, float32x4x3_t)
+
+/*
+** test_vst3q_f64:
+** st3 {v0\.2d - v2\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst3q_f64, float64_t *, float64x2x3_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/neon/vst4.c
b/gcc/testsuite/gcc.target/aarch64/neon/vst4.c
new file mode 100644
index 00000000000..3239555284c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/neon/vst4.c
@@ -0,0 +1,228 @@
+/* { dg-do compile } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "arm_neon_test.h"
+
+/*
+** test_vst4_mf8:
+** st4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_mf8, mfloat8_t *, mfloat8x8x4_t)
+
+/*
+** test_vst4_s8:
+** st4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_s8, int8_t *, int8x8x4_t)
+
+/*
+** test_vst4_u8:
+** st4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_u8, uint8_t *, uint8x8x4_t)
+
+/*
+** test_vst4_s16:
+** st4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_s16, int16_t *, int16x4x4_t)
+
+/*
+** test_vst4_u16:
+** st4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_u16, uint16_t *, uint16x4x4_t)
+
+/*
+** test_vst4_s32:
+** st4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_s32, int32_t *, int32x2x4_t)
+
+/*
+** test_vst4_u32:
+** st4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_u32, uint32_t *, uint32x2x4_t)
+
+/*
+** test_vst4_s64:
+** st1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_s64, int64_t *, int64x1x4_t)
+
+/*
+** test_vst4_u64:
+** st1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_u64, uint64_t *, uint64x1x4_t)
+
+/*
+** test_vst4_p8:
+** st4 {v0\.8b - v3\.8b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_p8, poly8_t *, poly8x8x4_t)
+
+/*
+** test_vst4_p16:
+** st4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_p16, poly16_t *, poly16x4x4_t)
+
+/*
+** test_vst4_p64:
+** st1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_p64, poly64_t *, poly64x1x4_t)
+
+/*
+** test_vst4_bf16:
+** st4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_bf16, bfloat16_t *, bfloat16x4x4_t)
+
+/*
+** test_vst4_f16:
+** st4 {v0\.4h - v3\.4h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_f16, float16_t *, float16x4x4_t)
+
+/*
+** test_vst4_f32:
+** st4 {v0\.2s - v3\.2s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_f32, float32_t *, float32x2x4_t)
+
+/*
+** test_vst4_f64:
+** st1 {v0\.1d - v3\.1d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4_f64, float64_t *, float64x1x4_t)
+
+/*
+** test_vst4q_mf8:
+** st4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_mf8, mfloat8_t *, mfloat8x16x4_t)
+
+/*
+** test_vst4q_s8:
+** st4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_s8, int8_t *, int8x16x4_t)
+
+/*
+** test_vst4q_u8:
+** st4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_u8, uint8_t *, uint8x16x4_t)
+
+/*
+** test_vst4q_s16:
+** st4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_s16, int16_t *, int16x8x4_t)
+
+/*
+** test_vst4q_u16:
+** st4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_u16, uint16_t *, uint16x8x4_t)
+
+/*
+** test_vst4q_s32:
+** st4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_s32, int32_t *, int32x4x4_t)
+
+/*
+** test_vst4q_u32:
+** st4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_u32, uint32_t *, uint32x4x4_t)
+
+/*
+** test_vst4q_s64:
+** st4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_s64, int64_t *, int64x2x4_t)
+
+/*
+** test_vst4q_u64:
+** st4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_u64, uint64_t *, uint64x2x4_t)
+
+/*
+** test_vst4q_p8:
+** st4 {v0\.16b - v3\.16b}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_p8, poly8_t *, poly8x16x4_t)
+
+/*
+** test_vst4q_p16:
+** st4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_p16, poly16_t *, poly16x8x4_t)
+
+/*
+** test_vst4q_p64:
+** st4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_p64, poly64_t *, poly64x2x4_t)
+
+/*
+** test_vst4q_bf16:
+** st4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_bf16, bfloat16_t *, bfloat16x8x4_t)
+
+/*
+** test_vst4q_f16:
+** st4 {v0\.8h - v3\.8h}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_f16, float16_t *, float16x8x4_t)
+
+/*
+** test_vst4q_f32:
+** st4 {v0\.4s - v3\.4s}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_f32, float32_t *, float32x4x4_t)
+
+/*
+** test_vst4q_f64:
+** st4 {v0\.2d - v3\.2d}, \[x0\]
+** ret
+*/
+TEST_STORE (vst4q_f64, float64_t *, float64x2x4_t)
diff --git a/gcc/testsuite/gcc.target/aarch64/pr99873_1.c
b/gcc/testsuite/gcc.target/aarch64/pr99873_1.c
index bc4d81e3ae5..b79ca06db6b 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr99873_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr99873_1.c
@@ -13,5 +13,10 @@ f (int *restrict x, int *restrict y, int *restrict z, int n)
}
}
-/* { dg-final { scan-assembler-times {\tld3\t} 2 } } */
-/* { dg-final { scan-assembler-times {\tst3\t} 1 } } */
+// SIMD loop body:
+/* { dg-final { scan-assembler-times { ld3 \{v[0-9]+\.4s - v[0-9]+\.4s\}}
2 } } */
+/* { dg-final { scan-assembler-times { st3 \{v[0-9]+\.4s - v[0-9]+\.4s\}}
1 } } */
+
+// SIMD loop tail:
+/* { dg-final { scan-assembler-times { ld3 \{v[0-9]+\.2s - v[0-9]+\.2s\}}
2 } } */
+/* { dg-final { scan-assembler-times { st3 \{v[0-9]+\.2s - v[0-9]+\.2s\}}
1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/vld2-1.c
b/gcc/testsuite/gcc.target/aarch64/vld2-1.c
index 0a5b97bfb75..5f0f0626b7a 100644
--- a/gcc/testsuite/gcc.target/aarch64/vld2-1.c
+++ b/gcc/testsuite/gcc.target/aarch64/vld2-1.c
@@ -43,4 +43,4 @@ void func3(float32x2x2_t *p, const float *p1, const float *p2)
}
/* 2 copy props for each function */
-/* { dg-final { scan-tree-dump-times "after previous" 6 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times "after previous" 3 "forwprop1" } } */
--
2.56.0