aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilco Dijkstra <wilco.dijkstra@arm.com>2024-07-02 17:37:04 +0100
committerWilco Dijkstra <wilco.dijkstra@arm.com>2024-07-05 13:03:35 +0100
commit100d353e545564931efaac90a089a4e8f3d42e6e (patch)
treee7b73450450e04b4c784e4fe14428cc7c71911b1
parent9f5620aed3976716e20e13c285dade56578d5bab (diff)
downloadgcc-100d353e545564931efaac90a089a4e8f3d42e6e.zip
gcc-100d353e545564931efaac90a089a4e8f3d42e6e.tar.gz
gcc-100d353e545564931efaac90a089a4e8f3d42e6e.tar.bz2
Arm: Fix disassembly error in Thumb-1 relaxed load/store [PR115188]
A Thumb-1 memory operand allows single-register LDMIA/STMIA. This doesn't get printed as LDR/STR with writeback in unified syntax, resulting in strange assembler errors if writeback is selected. To work around this, use the 'Uw' constraint that blocks writeback. Also use a new 'mem_and_no_t1_wback_op' which is a general memory operand that disallows writeback in Thumb-1. A few other patterns were using 'm' for Thumb-1 in a similar way, update these to also use 'mem_and_no_t1_wback_op' and 'Uw'. gcc: PR target/115188 * config/arm/arm.md (unaligned_loadsi): Use 'Uw' constraint and 'mem_and_no_t1_wback_op'. (unaligned_loadhiu): Likewise. (unaligned_storesi): Likewise. (unaligned_storehi): Likewise. * config/arm/predicates.md (mem_and_no_t1_wback_op): Add new predicate. * config/arm/sync.md (arm_atomic_load<mode>): Use 'Uw' constraint. (arm_atomic_store<mode>): Likewise. gcc/testsuite: PR target/115188 * gcc.target/arm/pr115188.c: Add new test. (cherry picked from commit d04c5537f5ae4a3acd3f5135347d7e2d8c218811)
-rw-r--r--gcc/config/arm/arm.md8
-rw-r--r--gcc/config/arm/predicates.md5
-rw-r--r--gcc/config/arm/sync.md4
-rw-r--r--gcc/testsuite/gcc.target/arm/pr115188.c10
4 files changed, 21 insertions, 6 deletions
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 1fd0014..13a8fbf 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -5011,7 +5011,7 @@
(define_insn "unaligned_loadsi"
[(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
- (unspec:SI [(match_operand:SI 1 "memory_operand" "m,Uw,m")]
+ (unspec:SI [(match_operand:SI 1 "mem_and_no_t1_wback_op" "Uw,Uw,m")]
UNSPEC_UNALIGNED_LOAD))]
"unaligned_access"
"@
@@ -5041,7 +5041,7 @@
(define_insn "unaligned_loadhiu"
[(set (match_operand:SI 0 "s_register_operand" "=l,l,r")
(zero_extend:SI
- (unspec:HI [(match_operand:HI 1 "memory_operand" "m,Uw,m")]
+ (unspec:HI [(match_operand:HI 1 "mem_and_no_t1_wback_op" "Uw,Uw,m")]
UNSPEC_UNALIGNED_LOAD)))]
"unaligned_access"
"@
@@ -5066,7 +5066,7 @@
(set_attr "type" "store_8")])
(define_insn "unaligned_storesi"
- [(set (match_operand:SI 0 "memory_operand" "=m,Uw,m")
+ [(set (match_operand:SI 0 "mem_and_no_t1_wback_op" "=Uw,Uw,m")
(unspec:SI [(match_operand:SI 1 "s_register_operand" "l,l,r")]
UNSPEC_UNALIGNED_STORE))]
"unaligned_access"
@@ -5081,7 +5081,7 @@
(set_attr "type" "store_4")])
(define_insn "unaligned_storehi"
- [(set (match_operand:HI 0 "memory_operand" "=m,Uw,m")
+ [(set (match_operand:HI 0 "mem_and_no_t1_wback_op" "=Uw,Uw,m")
(unspec:HI [(match_operand:HI 1 "s_register_operand" "l,l,r")]
UNSPEC_UNALIGNED_STORE))]
"unaligned_access"
diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md
index 4994c0c..197054b 100644
--- a/gcc/config/arm/predicates.md
+++ b/gcc/config/arm/predicates.md
@@ -907,3 +907,8 @@
;; A special predicate that doesn't match a particular mode.
(define_special_predicate "arm_any_register_operand"
(match_code "reg"))
+
+;; General memory operand that disallows Thumb-1 POST_INC.
+(define_predicate "mem_and_no_t1_wback_op"
+ (and (match_operand 0 "memory_operand")
+ (match_test "!(TARGET_THUMB1 && GET_CODE (XEXP (op, 0)) == POST_INC)")))
diff --git a/gcc/config/arm/sync.md b/gcc/config/arm/sync.md
index df8dbe1..0a8347f 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -65,7 +65,7 @@
(define_insn "arm_atomic_load<mode>"
[(set (match_operand:QHSI 0 "register_operand" "=r,l")
(unspec_volatile:QHSI
- [(match_operand:QHSI 1 "memory_operand" "m,m")]
+ [(match_operand:QHSI 1 "mem_and_no_t1_wback_op" "m,Uw")]
VUNSPEC_LDR))]
""
"ldr<sync_sfx>\t%0, %1"
@@ -81,7 +81,7 @@
)
(define_insn "arm_atomic_store<mode>"
- [(set (match_operand:QHSI 0 "memory_operand" "=m,m")
+ [(set (match_operand:QHSI 0 "mem_and_no_t1_wback_op" "=m,Uw")
(unspec_volatile:QHSI
[(match_operand:QHSI 1 "register_operand" "r,l")]
VUNSPEC_STR))]
diff --git a/gcc/testsuite/gcc.target/arm/pr115188.c b/gcc/testsuite/gcc.target/arm/pr115188.c
new file mode 100644
index 0000000..9a4022b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr115188.c
@@ -0,0 +1,10 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_arch_v6m_ok }
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v6m } */
+
+void init (int *p, int n)
+{
+ for (int i = 0; i < n; i++)
+ __atomic_store_4 (p + i, 0, __ATOMIC_RELAXED);
+}