diff options
author | Stam Markianos-Wright <stam.markianos-wright@arm.com> | 2022-12-30 11:25:22 +0000 |
---|---|---|
committer | Stam Markianos-Wright <stam.markianos-wright@arm.com> | 2022-12-30 11:25:22 +0000 |
commit | 4269a6567eb991e6838f40bda5be9e3a7972530c (patch) | |
tree | e589a6ae298d1f29b704bef1055a405eae8d3c86 /gcc/config | |
parent | cdc6bf44eec295805ae29a8aaddafd111de01c8e (diff) | |
download | gcc-4269a6567eb991e6838f40bda5be9e3a7972530c.zip gcc-4269a6567eb991e6838f40bda5be9e3a7972530c.tar.gz gcc-4269a6567eb991e6838f40bda5be9e3a7972530c.tar.bz2 |
Fix memory constraint on MVE v[ld/st][2/4] instructions [PR107714]
In the M-Class Arm-ARM:
https://developer.arm.com/documentation/ddi0553/bu/?lang=en
these MVE instructions only have '!' writeback variant and at:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107714
we found that the Um constraint would also allow through a
register offset writeback, resulting in an assembler error.
Here I have added a new constraint and predicate for these
instructions, which (uniquely, AFAICT), only support a `!` writeback
increment by the data size (inside the compiler this is a POST_INC).
No regressions in arm-none-eabi with MVE and MVE.FP.
gcc/ChangeLog:
PR target/107714
* config/arm/arm-protos.h (mve_struct_mem_operand): New protoype.
* config/arm/arm.cc (mve_struct_mem_operand): New function.
* config/arm/constraints.md (Ug): New constraint.
* config/arm/mve.md (mve_vst4q<mode>): Change constraint.
(mve_vst2q<mode>): Likewise.
(mve_vld4q<mode>): Likewise.
(mve_vld2q<mode>): Likewise.
* config/arm/predicates.md (mve_struct_operand): New predicate.
gcc/testsuite/ChangeLog:
PR target/107714
* gcc.target/arm/mve/intrinsics/vldst24q_reg_offset.c: New test.
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/arm/arm-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/arm/arm.cc | 18 | ||||
-rw-r--r-- | gcc/config/arm/constraints.md | 5 | ||||
-rw-r--r-- | gcc/config/arm/mve.md | 8 | ||||
-rw-r--r-- | gcc/config/arm/predicates.md | 4 |
5 files changed, 32 insertions, 4 deletions
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 550272f..8ea3811 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -122,6 +122,7 @@ extern int arm_coproc_mem_operand_wb (rtx, int); extern int neon_vector_mem_operand (rtx, int, bool); extern int mve_vector_mem_operand (machine_mode, rtx, bool); extern int neon_struct_mem_operand (rtx); +extern int mve_struct_mem_operand (rtx); extern rtx *neon_vcmla_lane_prepare_operands (rtx *); diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index b587561..31f2a7b 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -13737,6 +13737,24 @@ neon_vector_mem_operand (rtx op, int type, bool strict) return FALSE; } +/* Return TRUE if OP is a mem suitable for loading/storing an MVE struct + type. */ +int +mve_struct_mem_operand (rtx op) +{ + rtx ind = XEXP (op, 0); + + /* Match: (mem (reg)). */ + if (REG_P (ind)) + return arm_address_register_rtx_p (ind, 0); + + /* Allow only post-increment by the mode size. */ + if (GET_CODE (ind) == POST_INC) + return arm_address_register_rtx_p (XEXP (ind, 0), 0); + + return FALSE; +} + /* Return TRUE if OP is a mem suitable for loading/storing a Neon struct type. */ int diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index e5a36d2..121ec05 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -474,6 +474,11 @@ (and (match_code "mem") (match_test "TARGET_32BIT && arm_coproc_mem_operand (op, FALSE)"))) +(define_memory_constraint "Ug" + "@internal + In Thumb-2 state a valid MVE struct load/store address." + (match_operand 0 "mve_struct_operand")) + (define_memory_constraint "Uj" "@internal In ARM/Thumb-2 state a VFP load/store address that supports writeback diff --git a/gcc/config/arm/mve.md b/gcc/config/arm/mve.md index 3fe9db8..0c21db1 100644 --- a/gcc/config/arm/mve.md +++ b/gcc/config/arm/mve.md @@ -99,7 +99,7 @@ ;; [vst4q]) ;; (define_insn "mve_vst4q<mode>" - [(set (match_operand:XI 0 "neon_struct_operand" "=Um") + [(set (match_operand:XI 0 "mve_struct_operand" "=Ug") (unspec:XI [(match_operand:XI 1 "s_register_operand" "w") (unspec:MVE_VLD_ST [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] VST4Q)) @@ -9961,7 +9961,7 @@ ;; [vst2q]) ;; (define_insn "mve_vst2q<mode>" - [(set (match_operand:OI 0 "neon_struct_operand" "=Um") + [(set (match_operand:OI 0 "mve_struct_operand" "=Ug") (unspec:OI [(match_operand:OI 1 "s_register_operand" "w") (unspec:MVE_VLD_ST [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] VST2Q)) @@ -9990,7 +9990,7 @@ ;; (define_insn "mve_vld2q<mode>" [(set (match_operand:OI 0 "s_register_operand" "=w") - (unspec:OI [(match_operand:OI 1 "neon_struct_operand" "Um") + (unspec:OI [(match_operand:OI 1 "mve_struct_operand" "Ug") (unspec:MVE_VLD_ST [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] VLD2Q)) ] @@ -10018,7 +10018,7 @@ ;; (define_insn "mve_vld4q<mode>" [(set (match_operand:XI 0 "s_register_operand" "=w") - (unspec:XI [(match_operand:XI 1 "neon_struct_operand" "Um") + (unspec:XI [(match_operand:XI 1 "mve_struct_operand" "Ug") (unspec:MVE_VLD_ST [(const_int 0)] UNSPEC_VSTRUCTDUMMY)] VLD4Q)) ] diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index aab5a91..67f2fdb 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -876,6 +876,10 @@ (and (match_code "mem") (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2, true)"))) +(define_predicate "mve_struct_operand" + (and (match_code "mem") + (match_test "TARGET_HAVE_MVE && mve_struct_mem_operand (op)"))) + (define_predicate "neon_permissive_struct_operand" (and (match_code "mem") (match_test "TARGET_32BIT && neon_vector_mem_operand (op, 2, false)"))) |