]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AArch64: Fix memmove operand corruption [PR111121]
authorWilco Dijkstra <wilco.dijkstra@arm.com>
Tue, 26 Sep 2023 15:42:45 +0000 (16:42 +0100)
committerWilco Dijkstra <wilco.dijkstra@arm.com>
Thu, 28 Sep 2023 15:05:45 +0000 (16:05 +0100)
A MOPS memmove may corrupt registers since there is no copy of the input
operands to temporary registers.  Fix this by calling
aarch64_expand_cpymem_mops.

Reviewed-by: Richard Sandiford <richard.sandiford@arm.com>
gcc/ChangeLog/
PR target/111121
* config/aarch64/aarch64.md (aarch64_movmemdi): Add new expander.
(movmemdi): Call aarch64_expand_cpymem_mops for correct expansion.
* config/aarch64/aarch64.cc (aarch64_expand_cpymem_mops): Add support
for memmove.
* config/aarch64/aarch64-protos.h (aarch64_expand_cpymem_mops): Add new
function.

gcc/testsuite/ChangeLog/
PR target/111121
* gcc.target/aarch64/mops_4.c: Add memmove testcases.

gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64.cc
gcc/config/aarch64/aarch64.md
gcc/testsuite/gcc.target/aarch64/mops_4.c

index 3c8f4186689bd1e939407b0bf7929e0eb6f0c1ed..5c6802b4fe8b5671452ceab160caf6fbf63badbe 100644 (file)
@@ -789,6 +789,7 @@ bool aarch64_emit_approx_div (rtx, rtx, rtx);
 bool aarch64_emit_approx_sqrt (rtx, rtx, bool);
 tree aarch64_vector_load_decl (tree);
 void aarch64_expand_call (rtx, rtx, rtx, bool);
+bool aarch64_expand_cpymem_mops (rtx *, bool);
 bool aarch64_expand_cpymem (rtx *);
 bool aarch64_expand_setmem (rtx *);
 bool aarch64_float_const_zero_rtx_p (rtx);
index f1e98ea1ab6823c883368ccd542b73e9fa3b1747..aa920fc703a8f2ad7b4602ec7e55bcacf5ade7dc 100644 (file)
@@ -25313,10 +25313,11 @@ aarch64_copy_one_block_and_progress_pointers (rtx *src, rtx *dst,
   *dst = aarch64_progress_pointer (*dst);
 }
 
-/* Expand a cpymem using the MOPS extension.  OPERANDS are taken
-   from the cpymem pattern.  Return true iff we succeeded.  */
-static bool
-aarch64_expand_cpymem_mops (rtx *operands)
+/* Expand a cpymem/movmem using the MOPS extension.  OPERANDS are taken
+   from the cpymem/movmem pattern.  IS_MEMMOVE is true if this is a memmove
+   rather than memcpy.  Return true iff we succeeded.  */
+bool
+aarch64_expand_cpymem_mops (rtx *operands, bool is_memmove = false)
 {
   if (!TARGET_MOPS)
     return false;
@@ -25328,8 +25329,10 @@ aarch64_expand_cpymem_mops (rtx *operands)
   rtx dst_mem = replace_equiv_address (operands[0], dst_addr);
   rtx src_mem = replace_equiv_address (operands[1], src_addr);
   rtx sz_reg = copy_to_mode_reg (DImode, operands[2]);
-  emit_insn (gen_aarch64_cpymemdi (dst_mem, src_mem, sz_reg));
-
+  if (is_memmove)
+    emit_insn (gen_aarch64_movmemdi (dst_mem, src_mem, sz_reg));
+  else
+    emit_insn (gen_aarch64_cpymemdi (dst_mem, src_mem, sz_reg));
   return true;
 }
 
index 60133b541e9289610ce58116b0258a61f29bdc00..6d0f072a9dd6d094e8764a513222a9129d8296fa 100644 (file)
 }
 )
 
-(define_insn "aarch64_movmemdi"
+(define_expand "aarch64_movmemdi"
+  [(parallel
+     [(set (match_operand 2) (const_int 0))
+      (clobber (match_dup 3))
+      (clobber (match_dup 4))
+      (clobber (reg:CC CC_REGNUM))
+      (set (match_operand 0)
+          (unspec:BLK [(match_operand 1) (match_dup 2)] UNSPEC_MOVMEM))])]
+  "TARGET_MOPS"
+  {
+    operands[3] = XEXP (operands[0], 0);
+    operands[4] = XEXP (operands[1], 0);
+  }
+)
+
+(define_insn "*aarch64_movmemdi"
   [(parallel [
    (set (match_operand:DI 2 "register_operand" "+&r") (const_int 0))
    (clobber (match_operand:DI 0 "register_operand" "+&r"))
        && INTVAL (sz_reg) < aarch64_mops_memmove_size_threshold)
      FAIL;
 
-   rtx addr_dst = XEXP (operands[0], 0);
-   rtx addr_src = XEXP (operands[1], 0);
-
-   if (!REG_P (sz_reg))
-     sz_reg = force_reg (DImode, sz_reg);
-   if (!REG_P (addr_dst))
-     addr_dst = force_reg (DImode, addr_dst);
-   if (!REG_P (addr_src))
-     addr_src = force_reg (DImode, addr_src);
-   emit_insn (gen_aarch64_movmemdi (addr_dst, addr_src, sz_reg));
-   DONE;
+  if (aarch64_expand_cpymem_mops (operands, true))
+    DONE;
+  FAIL;
 }
 )
 
index 1b87759cb5e8bbcbb58cf63404d1d579d44b2818..dd796115cb4093251964d881e93bf4b98ade0c32 100644 (file)
@@ -50,6 +50,54 @@ copy3 (int *x, int *y, long z, long *res)
   *res = z;
 }
 
+/*
+** move1:
+**     mov     (x[0-9]+), x0
+**     cpyp    \[\1\]!, \[x1\]!, x2!
+**     cpym    \[\1\]!, \[x1\]!, x2!
+**     cpye    \[\1\]!, \[x1\]!, x2!
+**     str     x0, \[x3\]
+**     ret
+*/
+void
+move1 (int *x, int *y, long z, int **res)
+{
+  __builtin_memmove (x, y, z);
+  *res = x;
+}
+
+/*
+** move2:
+**     mov     (x[0-9]+), x1
+**     cpyp    \[x0\]!, \[\1\]!, x2!
+**     cpym    \[x0\]!, \[\1\]!, x2!
+**     cpye    \[x0\]!, \[\1\]!, x2!
+**     str     x1, \[x3\]
+**     ret
+*/
+void
+move2 (int *x, int *y, long z, int **res)
+{
+  __builtin_memmove (x, y, z);
+  *res = y;
+}
+
+/*
+** move3:
+**     mov     (x[0-9]+), x2
+**     cpyp    \[x0\]!, \[x1\]!, \1!
+**     cpym    \[x0\]!, \[x1\]!, \1!
+**     cpye    \[x0\]!, \[x1\]!, \1!
+**     str     x2, \[x3\]
+**     ret
+*/
+void
+move3 (int *x, int *y, long z, long *res)
+{
+  __builtin_memmove (x, y, z);
+  *res = z;
+}
+
 /*
 ** set1:
 **     mov     (x[0-9]+), x0