#define ARM_HAVE_V8HF_ARITH (ARM_HAVE_NEON_V8HF_ARITH || TARGET_HAVE_MVE_FLOAT)
#define ARM_HAVE_V4SF_ARITH (ARM_HAVE_NEON_V4SF_ARITH || TARGET_HAVE_MVE_FLOAT)
+/* The conditions under which vector modes are supported by load/store
+ instructions using Neon. */
+
+#define ARM_HAVE_NEON_V8QI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V16QI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V4HI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V8HI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V2SI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V4SI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V4HF_LDST TARGET_NEON_FP16INST
+#define ARM_HAVE_NEON_V8HF_LDST TARGET_NEON_FP16INST
+#define ARM_HAVE_NEON_V4BF_LDST TARGET_BF16_SIMD
+#define ARM_HAVE_NEON_V8BF_LDST TARGET_BF16_SIMD
+#define ARM_HAVE_NEON_V2SF_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V4SF_LDST TARGET_NEON
+#define ARM_HAVE_NEON_DI_LDST TARGET_NEON
+#define ARM_HAVE_NEON_V2DI_LDST TARGET_NEON
+
+/* The conditions under which vector modes are supported by load/store
+ instructions by any vector extension. */
+
+#define ARM_HAVE_V8QI_LDST (ARM_HAVE_NEON_V8QI_LDST || TARGET_REALLY_IWMMXT)
+#define ARM_HAVE_V4HI_LDST (ARM_HAVE_NEON_V4HI_LDST || TARGET_REALLY_IWMMXT)
+#define ARM_HAVE_V2SI_LDST (ARM_HAVE_NEON_V2SI_LDST || TARGET_REALLY_IWMMXT)
+
+#define ARM_HAVE_V16QI_LDST (ARM_HAVE_NEON_V16QI_LDST || TARGET_HAVE_MVE)
+#define ARM_HAVE_V8HI_LDST (ARM_HAVE_NEON_V8HI_LDST || TARGET_HAVE_MVE)
+#define ARM_HAVE_V4SI_LDST (ARM_HAVE_NEON_V4SI_LDST || TARGET_HAVE_MVE)
+#define ARM_HAVE_DI_LDST ARM_HAVE_NEON_DI_LDST
+#define ARM_HAVE_V2DI_LDST ARM_HAVE_NEON_V2DI_LDST
+
+#define ARM_HAVE_V4HF_LDST ARM_HAVE_NEON_V4HF_LDST
+#define ARM_HAVE_V2SF_LDST ARM_HAVE_NEON_V2SF_LDST
+
+#define ARM_HAVE_V4BF_LDST ARM_HAVE_NEON_V4BF_LDST
+#define ARM_HAVE_V8BF_LDST ARM_HAVE_NEON_V8BF_LDST
+
+#define ARM_HAVE_V8HF_LDST (ARM_HAVE_NEON_V8HF_LDST || TARGET_HAVE_MVE_FLOAT)
+#define ARM_HAVE_V4SF_LDST (ARM_HAVE_NEON_V4SF_LDST || TARGET_HAVE_MVE_FLOAT)
+
/* The register numbers in sequence, for passing to arm_gen_load_multiple. */
extern int arm_regs_in_sequence[];
[(set_attr "type" "coproc")
(set_attr "length" "8")]
)
+
+(define_insn "*movmisalign<mode>_mve_store"
+ [(set (match_operand:MVE_VLD_ST 0 "neon_permissive_struct_operand" "=Um")
+ (unspec:MVE_VLD_ST [(match_operand:MVE_VLD_ST 1 "s_register_operand" " w")]
+ UNSPEC_MISALIGNED_ACCESS))]
+ "((TARGET_HAVE_MVE && VALID_MVE_SI_MODE (<MODE>mode))
+ || (TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE (<MODE>mode)))
+ && !BYTES_BIG_ENDIAN && unaligned_access"
+ "vstr<V_sz_elem1>.<V_sz_elem>\t%q1, %E0"
+ [(set_attr "type" "mve_store")]
+)
+
+
+(define_insn "*movmisalign<mode>_mve_load"
+ [(set (match_operand:MVE_VLD_ST 0 "s_register_operand" "=w")
+ (unspec:MVE_VLD_ST [(match_operand:MVE_VLD_ST 1 "neon_permissive_struct_operand" " Um")]
+ UNSPEC_MISALIGNED_ACCESS))]
+ "((TARGET_HAVE_MVE && VALID_MVE_SI_MODE (<MODE>mode))
+ || (TARGET_HAVE_MVE_FLOAT && VALID_MVE_SF_MODE (<MODE>mode)))
+ && !BYTES_BIG_ENDIAN && unaligned_access"
+ "vldr<V_sz_elem1>.<V_sz_elem>\t%q0, %E1"
+ [(set_attr "type" "mve_load")]
+)
neon_disambiguate_copy (operands, dest, src, 4);
})
-(define_expand "movmisalign<mode>"
- [(set (match_operand:VDQX 0 "neon_perm_struct_or_reg_operand")
- (unspec:VDQX [(match_operand:VDQX 1 "neon_perm_struct_or_reg_operand")]
- UNSPEC_MISALIGNED_ACCESS))]
- "TARGET_NEON && !BYTES_BIG_ENDIAN && unaligned_access"
-{
- rtx adjust_mem;
- /* This pattern is not permitted to fail during expansion: if both arguments
- are non-registers (e.g. memory := constant, which can be created by the
- auto-vectorizer), force operand 1 into a register. */
- if (!s_register_operand (operands[0], <MODE>mode)
- && !s_register_operand (operands[1], <MODE>mode))
- operands[1] = force_reg (<MODE>mode, operands[1]);
-
- if (s_register_operand (operands[0], <MODE>mode))
- adjust_mem = operands[1];
- else
- adjust_mem = operands[0];
-
- /* Legitimize address. */
- if (!neon_vector_mem_operand (adjust_mem, 2, true))
- XEXP (adjust_mem, 0) = force_reg (Pmode, XEXP (adjust_mem, 0));
-
-})
-
(define_insn "*movmisalign<mode>_neon_store"
[(set (match_operand:VDX 0 "neon_permissive_struct_operand" "=Um")
(unspec:VDX [(match_operand:VDX 1 "s_register_operand" " w")]
&& ARM_HAVE_<MODE>_ARITH)) && !BYTES_BIG_ENDIAN"
)
+(define_expand "movmisalign<mode>"
+ [(set (match_operand:VDQX 0 "neon_perm_struct_or_reg_operand")
+ (unspec:VDQX [(match_operand:VDQX 1 "neon_perm_struct_or_reg_operand")]
+ UNSPEC_MISALIGNED_ACCESS))]
+ "ARM_HAVE_<MODE>_LDST && !BYTES_BIG_ENDIAN && unaligned_access"
+{
+ rtx adjust_mem;
+ /* This pattern is not permitted to fail during expansion: if both arguments
+ are non-registers (e.g. memory := constant, which can be created by the
+ auto-vectorizer), force operand 1 into a register. */
+ if (!s_register_operand (operands[0], <MODE>mode)
+ && !s_register_operand (operands[1], <MODE>mode))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+
+ if (s_register_operand (operands[0], <MODE>mode))
+ adjust_mem = operands[1];
+ else
+ adjust_mem = operands[0];
+
+ /* Legitimize address. */
+ if (!neon_vector_mem_operand (adjust_mem, 2, true))
+ XEXP (adjust_mem, 0) = force_reg (Pmode, XEXP (adjust_mem, 0));
+})
functions above. */
/* { dg-final { scan-assembler-times {vneg.s[0-9]+ q[0-9]+, q[0-9]+} 6 } } */
/* { dg-final { scan-assembler-times {vneg.f[0-9]+ q[0-9]+, q[0-9]+} 2 } } */
+/* { dg-final { scan-assembler-times {vldr[bhw].[0-9]+\tq[0-9]+} 8 } } */
+/* { dg-final { scan-assembler-times {vstr[bhw].[0-9]+\tq[0-9]+} 8 } } */
+/* { dg-final { scan-assembler-not {orr\tr[0-9]+, r[0-9]+, r[0-9]+} } } */