Re: [PATCH v3] Arm: Fix disassembly error in Thumb-1 relaxed load/store [PR115188]

2024-06-28 Thread Richard Earnshaw (lists)
On 27/06/2024 17:16, Wilco Dijkstra wrote:
> Hi Richard,
> 
>> Doing just this will mean that the register allocator will have to undo a 
>> pre/post memory operand that was accepted by the predicate (memory_operand). 
>>  I think we really need a tighter predicate (lets call it noautoinc_mem_op) 
>> here to avoid that.  Note that the existing uses of Uw also had another 
>> alternative that did permit 'm', so this wasn't previously practical, but 
>> they had alternative ways of being reloaded.
>>
>> No, sorry that won't work; there's another 'm' alternative here as well.
>> The correct fix is to add alternatives for T1, I think, similar to the one 
>> in thumb1_movsi_insn.
>>
>> Also, by observation I think there's a similar problem in the load 
>> operations.
> 
> Just using 'Uw' works fine, but restricting the memory operand too is better 
> indeed.
> I added 'restricted_memory_operand' that only disallows Thumb-1 postincrement.
> 
> There were also a few more cases in unaligned accesses where 'm' was used 
> incorrectly when
> emitting Thumb-1 LDR/STR alternatives (and where no LDM/STMis allowed), so 
> those also use
> 'Uw' and 'restricted_memory_operand'.
> 
> Long term it seems like a better idea is to remove support this odd 
> post-increment
> in general memory operand and only emit it from a peephole pass.
> 
> Cheers,
> Wilco
> 
> 
> v3: Use 'Uw' in a few more cases. Add 'restricted_memory_operand'.
> 
> 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 'restricted_memory_operand'
> 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 'restricted_memory_operand' and 'Uw'.
> 
> Passes bootstrap & regress, OK for commit (and backport to GCC14.2)?

I'm not a major fan of the name restricted_memory_operand as it doesn't 
describe which restriction is being applied and something like 
t1_restricted_memory_operand would not be any clearer.  Perhaps 
mem_and_no_t1_wback_op would be better?

OK with that change.

R.

> 
> gcc:
> PR target/115188
> * config/arm/arm.md (unaligned_loadsi): Use 'Uw' constraint and
> 'restricted_memory_operand'.
> (unaligned_loadhiu): Likewise.
> (unaligned_storesi): Likewise.
> (unaligned_storehi): Likewise.
> * config/arm/predicates.md (restricted_memory_operand): Add new 
> predicate.
> * config/arm/sync.md (arm_atomic_load): Use 'Uw' constraint.
> (arm_atomic_store): Likewise.
> 
> gcc/testsuite:
> PR target/115188
> * gcc.target/arm/pr115188.c: Add new test.
> 
> ---
> 
> diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
> index 
> f47e036a8034ed16c61bbd753c7a7cd3efb1ecbd..c962a9341779e4da38f4e1afb26d4a364fc5aee4
>  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 "restricted_memory_operand" "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 "restricted_memory_operand" 
> "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 "restricted_memory_operand" "=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 "restricted_memory_operand" "=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 
> 4994c0c57d6431117c16f7a05e800821dee93408..3dfe381c098c06517dca6026f8dafe87b46135ae
>  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"

Re: [PATCH v3] Arm: Fix disassembly error in Thumb-1 relaxed load/store [PR115188]

2024-06-27 Thread Wilco Dijkstra
Hi Richard,

> Doing just this will mean that the register allocator will have to undo a 
> pre/post memory operand that was accepted by the predicate (memory_operand).  
> I think we really need a tighter predicate (lets call it noautoinc_mem_op) 
> here to avoid that.  Note that the existing uses of Uw also had another 
> alternative that did permit 'm', so this wasn't previously practical, but 
> they had alternative ways of being reloaded.
>
> No, sorry that won't work; there's another 'm' alternative here as well.
> The correct fix is to add alternatives for T1, I think, similar to the one in 
> thumb1_movsi_insn.
> 
> Also, by observation I think there's a similar problem in the load operations.

Just using 'Uw' works fine, but restricting the memory operand too is better 
indeed.
I added 'restricted_memory_operand' that only disallows Thumb-1 postincrement.

There were also a few more cases in unaligned accesses where 'm' was used 
incorrectly when
emitting Thumb-1 LDR/STR alternatives (and where no LDM/STMis allowed), so 
those also use
'Uw' and 'restricted_memory_operand'.

Long term it seems like a better idea is to remove support this odd 
post-increment
in general memory operand and only emit it from a peephole pass.

Cheers,
Wilco


v3: Use 'Uw' in a few more cases. Add 'restricted_memory_operand'.

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 'restricted_memory_operand'
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 'restricted_memory_operand' and 'Uw'.

Passes bootstrap & regress, OK for commit (and backport to GCC14.2)?

gcc:
PR target/115188
* config/arm/arm.md (unaligned_loadsi): Use 'Uw' constraint and
'restricted_memory_operand'.
(unaligned_loadhiu): Likewise.
(unaligned_storesi): Likewise.
(unaligned_storehi): Likewise.
* config/arm/predicates.md (restricted_memory_operand): Add new 
predicate.
* config/arm/sync.md (arm_atomic_load): Use 'Uw' constraint.
(arm_atomic_store): Likewise.

gcc/testsuite:
PR target/115188
* gcc.target/arm/pr115188.c: Add new test.

---

diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 
f47e036a8034ed16c61bbd753c7a7cd3efb1ecbd..c962a9341779e4da38f4e1afb26d4a364fc5aee4
 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 "restricted_memory_operand" "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 "restricted_memory_operand" 
"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 "restricted_memory_operand" "=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 "restricted_memory_operand" "=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 
4994c0c57d6431117c16f7a05e800821dee93408..3dfe381c098c06517dca6026f8dafe87b46135ae
 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 "restricted_memory_operand"
+  (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 
df8dbe170cacb6b60d56a6f19aadd5a6c9c51f7a..7696c1a6f9819cfcbc9008f58431b9c2f08cb0ce
 100644
--- a/gcc/config/arm/sync.md
+++ b/gcc/config/arm/sync.md
@@ -65,7 +65,7 @@
 (define_insn "arm_atomic_load"
   [(set (m